Яка мета використання дужок (тобто {}) для однорядного if або циклу?


321

Я читаю конспекти лекцій свого лектора C ++, і він написав наступне:

  1. Використовуйте відступ // Добре
  2. Ніколи не покладайтеся на пріоритет оператора - Завжди використовуйте дужки // ОК
  3. Завжди використовуйте блок {} - навіть для одного рядка // не в порядку , чому ???
  4. Об'єкт Const у лівій частині порівняння // ОК
  5. Використовуйте неподписані для змінних, які> = 0 // хороший трюк
  6. Встановіть покажчик на NULL після видалення - захист подвійного видалення // не погано

Третя методика мені не зрозуміла: що я отримав би, розмістивши один рядок у a { ... }?

Наприклад, візьміть цей дивний код:

int j = 0;
for (int i = 0 ; i < 100 ; ++i)
{
    if (i % 2 == 0)
    {
        j++;
    }
}

і замініть його на:

int j = 0;
for (int i = 0 ; i < 100 ; ++i)
    if (i % 2 == 0)
        j++;

Яка користь від використання 1-ї версії?


256
Зрозумілість та ретельність. Не відразу очевидно, до якого блоку операторів 'j ++' належить, і що додавання коду після нього не буде пов’язане з оператором if.
Ліс та дерева

27
Мені завжди казали використовувати фігурні дужки {} для цих рядків з кількох причин. Це робить код зрозумілішим для читання. Також комусь за шість місяців може знадобитися відредагувати ваш код, тому чіткість є важливою, а в дужках помилка рідше трапиться. Нічого технічно більш правильного в цьому немає, це лише питання належної практики. Майте на увазі, що проект може мати тисячі і тисячі рядків коду, щоб якийсь новий хлопець пронизав!
RossC

30
Я не згоден з 6, оскільки це приховає подвійне видалення та потенційно приховає логічні помилки.
Лучіан Григоре

28
# 5 може бути складно - розглянути цей цикл: for (unsigned i = 100; i >= 0; --i).
Арчі

36
Btw, (i % 2 == 0)суперечить (2). Ви покладаєтесь на пріоритет оператора, і сенс, звичайно, ((i % 2) == 0)а не (i % (2 == 0)). Я б класифікував правило 2 як "дійсні настрої, але" завжди "неправильно".
Стів Джессоп

Відповіді:


509

Спробуємо також змінити iпри збільшенні j:

int j = 0;
for (int i = 0 ; i < 100 ; ++i)
    if (i % 2 == 0)
        j++;
        i++;

О ні! Походить із Python, це виглядає нормально, але насправді це не так, як це еквівалентно:

int j = 0;
for (int i = 0 ; i < 100 ; ++i)
    if (i % 2 == 0)
        j++;
i++;

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

Ще одна дуже вагома причина вказується у відповіді ta.speot.is .

Третій, який я можу придумати, - це вкладені if:

if (cond1)
   if (cond2) 
      doSomething();

Тепер припустимо, що ви хочете, doSomethingElse()коли cond1це не виконано (нова функція). Тому:

if (cond1)
   if (cond2) 
      doSomething();
else
   doSomethingElse();

що, очевидно, неправильно, оскільки elseасоціюється з внутрішнім if.


Редагувати: Оскільки до цього привертають певну увагу, я проясню свою думку. Питання, на яке я відповідав:

Яка користь від використання 1-ї версії?

Який я описав. Є деякі переваги. Але, IMO, правила "завжди" не завжди застосовуються. Тому я не повністю підтримую

Завжди використовуйте блок {} - навіть для одного рядка // не в порядку, чому ???

Я не кажу, що завжди використовуйте {}блок. Якщо це досить проста умова та поведінка, не робіть цього. Якщо ви підозрюєте, що хтось може зайти пізніше, і змініть код, щоб додати функціональність, зробіть це.


5
@Science_Fiction: Це правда, але якщо ви додасте i++ раніше j++ , обидві змінні все ще будуть мати область застосування при їх використанні.
Майк Сеймур

26
Це звучить дуже розумно, але нехтує тим, що редактор робить відступ, а не ви, і він буде відступати i++;так, що відразу показує, що він не є частиною циклу. (Раніше це, можливо, було розумним аргументом, і я бачив такі проблеми. Близько 20 років тому. Не з тих пір.)
Джеймс Канзе

43
@James: це не факт, але це ваш робочий процес. І робочий процес дуже багато людей, але не у всіх. Я не думаю, що це обов'язково помилка трактувати джерело C ++ як звичайний текстовий файл, а не вихід редактора WYSIWYG (vi / emacs / Visual Studio), який застосовує правила форматування. Таким чином, це правило є редактором-агностиком понад те, що вам потрібно, але не виходить за рамки того, що люди реально використовують для редагування C ++. Звідси "оборонний".
Стів Джессоп

31
@JamesKanze Ви справді покладаєтесь на припущення, що всі завжди працюють у потужних ІДЕ? Останній КІ написав був у Нано. Навіть враховуючи, що одне з перших речей, які я прагну вимкнути в IDE, - це автоматичне відступ - тому що IDE має тенденцію перешкоджати моєму нелінійному робочому процесу, намагаючись виправити мої «помилки» на основі неповної інформації . IDE не дуже добре в автоматичному відступі природного потоку кожного програміста. Ті програмісти, які використовують такі функції, як правило, об'єднують свій стиль зі своїм IDE, що добре, якщо ви використовуєте лише одну IDE, але не для того, щоб працювати у багатьох.
Rushyo

10
"Це дурна помилка, але така, яка може зробити навіть досвідчений програміст". - Як я вже сказав у своїй відповіді, я не вірю в це. Я думаю, що це цілком надуманий випадок, який насправді не створює проблем.
Конрад Рудольф

324

Дуже легко випадково змінити контрольний потік з коментарями, якщо ви не використовуєте {та }. Наприклад:

if (condition)
  do_something();
else
  do_something_else();

must_always_do_this();

Якщо ви прокоментуєте коментар do_something_else()в одному рядку, ви закінчите це:

if (condition)
  do_something();
else
  //do_something_else();

must_always_do_this();

Вона компілюється, але must_always_do_this()не завжди її називають.

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


3
Ох хлопчик !! це визначена поведінка, яка must_always_do_this();буде виконуватися, якщо ви коментуєте // do_something_else ();
Містер Анубіс

1
@Supr, як було написано вперше, він говорить, що важко порушити правильний потік, якщо ви використовуєте дужки, а потім наводить приклад того, як легко перервати, не маючи належним чином
закреслений

20
Я натрапив на це лише днями. if(debug) \n //print(info);. В основному вийняли цілу бібліотеку.
Кевін

4
Fortunately we caught it in code review.Ой! Це звучить так неправильно. Fortunately we caught it in unit tests.було б набагато краще!
BЈович

4
@ BЈовић Але що робити, якщо код був у одиничному тесті? Розум хизується. (Жартую, це застаріле додаток. Немає одиничних тестів.)
ta.speot.is

59

У мене є сумніви щодо компетенції викладача. Враховуючи його моменти:

  1. добре
  2. Хтось справді писав би (чи хотів би прочитати) (b*b) - ((4*a)*c)? Деякі пріоритети очевидні (або повинні бути), а додаткові дужки просто додають плутанини. (З іншого боку, ви _should_ використовувати дужки в менш очевидних випадках, навіть якщо ви знаєте, що вони не потрібні.)
  3. Типу. Існує два широких розповсюдження для поширення умовних умов і циклів:
    if (cond) {
        код;
    }
    
    і:
    якщо (умовно)
    {
        код;
    }
    
    По-перше, я погодився б з ним. Відкриття {не так видно, тому краще припустити, що воно завжди є. У другому, однак, я (і більшість людей, з якими я працював) не маю жодних проблем із пропусканням дужок для одного твердження. (За умови, звичайно, що відступ є систематичним і ви використовуєте цей стиль послідовно. (І багато дуже хороших програмістів, які пишуть дуже читабельний код, опускають дужки навіть при форматуванні в перший спосіб.)
  4. НІ . Такі речі if ( NULL == ptr )досить некрасиві, щоб перешкодити читанню. Пишіть порівняння інтуїтивно. (Що в багатьох випадках призводить до постійної праворуч.) Його 4 - погана порада; все, що робить код неприродним, робить його менш читабельним.
  5. НІ . Все, але intзарезервовано для особливих випадків. Для досвідчених програмістів C і C ++ використання unsignedоператорів бітових сигналів. C ++ не має реального типу кардинала (або будь-якого іншого ефективного типу піддіапазону); unsignedне працює для числових значень через правила просування. Числові значення, для яких жодні арифметичні операції не мали б сенсу, як серійні номери, імовірно можуть бути unsigned. Я б заперечував проти цього, оскільки він надсилає неправильне повідомлення: побітні операції теж не мають сенсу. Основне правило полягає в тому, що цілісні типи є int_unless_ є вагома причина використання іншого типу.
  6. НІ . Це робити систематично - вводить в оману і насправді нічого не захищає. У суворому коді OO delete this;часто найчастіший випадок (і ви не можете встановити thisйого NULL), інакше більшість deleteє в деструкторах, тому ви не можете отримати доступ до вказівника пізніше. І встановити його так, щоб NULLнічого не стосувалося до інших покажчиків, що плавають навколо. Систематичне налаштування покажчика NULLдає помилкове відчуття безпеки і насправді нічого не купує у вас.

Подивіться на код у будь-якому з типових посилань. Stroustrup порушує будь-яке подане вами правило, за винятком першого, наприклад.

Я б запропонував вам знайти іншого викладача. Той, хто насправді знає, про що говорить.


13
Число 4 може бути некрасивим, проте в цьому є мета. Він намагається запобігти if (ptr = NULL). Я не думаю, що я ніколи не використовував delete this, це частіше, ніж я бачив? Я не схильний думати, що встановлення вказівника на NULL після використання - це погано, ніж робити YMMV. Можливо, це лише я, але більшість його вказівок не здаються такими поганими.
Фредрагон

16
@Firedragon: Більшість компіляторів попередитимуть, if (ptr = NULL)якщо ви не напишете це як if ((ptr = NULL)). Доведеться погодитися з Джеймсом Канзе, що потворність того, що NULLспочатку зробить це для мене певним НІ.
Лев

34
@JamesKanze: Я мушу сказати, що я не згоден з більшістю того, що ви тут висловили, хоча я ціную і поважаю ваші аргументи за те, що ви прийшли до них. Для досвідчених програмістів C і C ++ використання операторів бітових сигналів без підпису сигналів. - Я зовсім не згоден: використання бітових операторів сигналізує про використання бітових операторів. Для мене використання unsignedвказує на прагнення програміста, що змінна повинна представляти лише додатні числа. Змішування з підписаними номерами зазвичай спричиняє попередження компілятора, яке, мабуть, було те, що лектор мав намір.
Компонент 10

18
Для досвідчених програмістів на C і C ++ використання операторів бітових непідписаних сигналів Або ні. size_t, хтось?
ta.speot.is

16
@James Kanze, врахуйте мету. Ви порівнюєте код, створений досвідченим програмістом, з прикладами навчання. Ці правила надає викладач, оскільки вони є типом помилок, які він бачить у своїх студентах. Маючи досвід, студенти можуть розслабитися або знехтувати цими абсолютами.
Джошуа Шейн Ліберман

46

Усі інші відповіді захищають правило вашого лектора 3.

Дозвольте сказати, що я згоден з вами: правило є зайвим, і я б не радив його. Це правда, що це теоретично запобігає помилкам, якщо ви завжди додаєте фігурні дужки. З іншого боку, я ніколи не стикався з цією проблемою в реальному житті : всупереч тому, що означають інші відповіді, я не раз забував додати фігурні дужки, коли вони стануть необхідними. Якщо ви користуєтесь належним відступом, відразу стає очевидним, що вам потрібно додати фігурні дужки ще раз, ніж один вислів з відступом.

Відповідь «Компонента 10» фактично підкреслює єдиний можливий випадок, коли це дійсно може призвести до помилки. Але з іншого боку, заміна коду регулярним виразом завжди вимагає величезної обережності.

Тепер давайте розглянемо іншу сторону медалі: чи є недолік завжди використовувати фігурні дужки? Інші відповіді просто ігнорують цей момент. Але є і недолік: він займає багато вертикального простору на екрані, а це, в свою чергу, може зробити ваш код нечитабельним, оскільки це означає, що вам потрібно прокручувати більше, ніж потрібно.

Розглянемо функцію з великою кількістю охоронних застережень на початку (і так, наступним є поганий код C ++, але в інших мовах це було б досить звичайною ситуацією):

void some_method(obj* a, obj* b)
{
    if (a == nullptr)
    {
        throw null_ptr_error("a");
    }
    if (b == nullptr)
    {
        throw null_ptr_error("b");
    }
    if (a == b)
    {
        throw logic_error("Cannot do method on identical objects");
    }
    if (not a->precondition_met())
    {
        throw logic_error("Precondition for a not met");
    }

    a->do_something_with(b);
}

Це жахливий код, і я твердо стверджую, що наступне набагато читабельніше:

void some_method(obj* a, obj* b)
{
    if (a == nullptr)
        throw null_ptr_error("a");
    if (b == nullptr)
        throw null_ptr_error("b");
    if (a == b)
        throw logic_error("Cannot do method on identical objects");
    if (not a->precondition_met())
        throw logic_error("Precondition for a not met");

    a->do_something_with(b);
}

Аналогічно, короткі вкладені петлі виграють від опускання фігурних дужок:

matrix operator +(matrix const& a, matrix const& b) {
    matrix c(a.w(), a.h());

    for (auto i = 0; i < a.w(); ++i)
        for (auto j = 0; j < a.h(); ++j)
            c(i, j) = a(i, j) + b(i, j);

    return c;
}

Порівняти з:

matrix operator +(matrix const& a, matrix const& b) {
    matrix c(a.w(), a.h());

    for (auto i = 0; i < a.w(); ++i)
    {
        for (auto j = 0; j < a.h(); ++j)
        {
            c(i, j) = a(i, j) + b(i, j);
        }
    }

    return c;
}

Перший код - стислий; другий код роздутий.

І так, це можна певною мірою пом'якшити , поставивши вступну дужку на попередній рядок. Але це все одно буде менш читабельним, ніж код без будь-яких фігурних дужок.

Коротше кажучи: не пишіть зайвий код, який займає місце на екрані.


26
Якщо ви не вірите в написання коду, який зайво займає простір на екрані, тоді у вас немає жодного бізнесу, щоб поставити вступну дужку на свою лінію. Напевно, зараз мені доведеться гнути і бігти від святої помсти GNU, але серйозно - або ви хочете, щоб ваш код був вертикально компактним, або ви цього не робите. І якщо ви це робите, не робіть речей, розроблених виключно, щоб зробити ваш код менш вертикально компактним. Але , як ви говорите, зафіксувавши , що ви по- , як і раніше також необхідно видалити зайві дужки. А може просто написати if (a == nullptr) { throw null_ptr_error("a"); }як один рядок.
Стів Джессоп

6
@Steve Справді, я б поставив відкриває фігурну дужку на попередньому рядку, з тієї причини , ви заявили. Я використовував інший стиль тут, щоб зробити більш очевидним, наскільки екстремальною може бути різниця.
Конрад Рудольф

9
+1 Я повністю погоджуюся, що ваш перший приклад читати набагато простіше без дужок. У другому прикладі мій особистий стиль кодування полягає у використанні брекетів на зовнішній для циклу, а не на внутрішній. Я не погоджуюся з @SteveJessop щодо того, щоб бути одним крайнім або іншим щодо вертикально компактного коду. Я опускаю додаткові дужки з одноклавишниками, щоб зменшити вертикальний простір, але я ставлю свої відкривальні дужки на нову лінію, тому що мені легше бачити область, коли брекети вишиковуються. Мета - читабельність, а іноді це означає використання більше вертикального простору, в інших випадках - використання менше.
Travesty3

22
"Я ніколи не стикався з цією проблемою в реальному житті": пощастило вам. Такі речі не просто спалюють вас, вони дають вам 90% опіки третього ступеня (і це лише кілька шарів управління, які вимагають виправити пізно ввечері).
Річард

9
@Richard Я просто не купую цього. Як я пояснював у чаті, навіть якщо ця помилка повинна колись статися (що я вважаю малоймовірною), це неправда виправити, як тільки ви подивитеся на слід стека, тому що очевидно, де помилка знаходиться лише при перегляді коду. Ваше перебільшене твердження повністю абсолютно безпідставне.
Конрад Рудольф

40

Кодова база, над якою я працюю, розсипається кодом людьми, що мають патологічну неприязнь до брекетів, а для людей, які приходять згодом, це дійсно може змінити ремонтопридатність.

Найбільш частий проблемний приклад, з яким я стикався, це:

if ( really incredibly stupidly massively long statement that exceeds the width of the editor) do_foo;
    this_looks_like_a_then-statement_but_isn't;

Тож коли я приходжу і хочу додати тодішнє твердження, я можу легко закінчити це, якщо не буду обережним:

if ( really incredibly stupidly massively long statement that exceeds the width of the editor) do_foo;
{
    this_looks_like_a_then-statement_but_isn't;
    i_want_this_to_be_a_then-statement_but_it's_not;
}

Враховуючи, що для додавання дужок потрібно ~ 1 секунда, і ви можете заощадити як мінімум кілька заплутаних хвилин налагодження, чому б ви ніколи не пішли з варіантом зі зменшеною двозначністю? Мені це здається хибною економією.


16
Чи не проблема в цьому прикладі в неправильному відступі та занадто довгих рядках, а не в дужках?
Honza Brabec

7
Так, але слідування керівництву щодо дизайну / кодування, які є лише "безпечними", припускаючи, що люди також дотримуються інших вказівок (наприклад, не мають занадто довгих рядків), викликає проблеми. Якби дужки були з самого початку, неможливо було б закінчитися неправильним if-блоком у цій ситуації.
варення

16
Як би додавання брекетів (щоб це if(really long...editor){ do_foo;}допомогло вам уникнути цього випадку? Схоже, проблема все одно буде однаковою. Особисто я вважаю за краще уникати дужок, коли це не потрібно, однак це не має нічого спільного з часом, необхідним для їх написання, але меншою читабельністю) завдяки двом зайвим рядкам у коді
Grizzly

1
Хороший момент - я припускав, що примусове використання брекетів також призведе до того, що вони будуть розміщені в розумному місці, але, звичайно, хтось вирішив ускладнити справи, може поставити їх у відповідність, як у вашому прикладі. Я думаю, що більшість людей не хотіли б.
повидло

2
Перше і останнє, що я роблю, коли торкаюся файлу, це натиснути кнопку автоформатування. Це усуває більшість цих питань.
Джонатан Аллен

20

Мій 2с:

Використовуйте відступ

Очевидно

Ніколи не покладайтеся на пріоритет оператора - Завжди використовуйте дужки

Я б не використовував слова "ніколи і" завжди ", але загалом я вважаю, що це правило є корисним. У деяких мовах (Lisp, Smalltalk) це питання не є проблемою.

Завжди використовуйте блок {}, навіть для одного рядка

Я ніколи цього не робив і ніколи не мав жодної проблеми, але я бачу, як це може бути корисним для студентів, особливо. якби вони вивчали Пітона раніше.

Об'єкт Const зліва порівняння

Умови йоди? Ні, будь ласка. Це шкодить читабельності. Просто використовуйте максимальний рівень попередження при складанні коду.

Використовуйте неподписані для змінних, що>> 0

ДОБРЕ. Досить смішно, я чув, що Stroustrup не погоджується.

Встановіть покажчик на NULL після видалення - захист подвійного видалення

Погана порада! Ніколи не має вказівника, який вказує на видалений або неіснуючий об'єкт.


5
+1 лише для останньої точки. Сирий покажчик у будь-якому випадку не має власної пам'яті.
Конрад Рудольф

2
Що стосується використання без підпису: не тільки Stroustrup, але і K&R (в С), Herb Sutter і (я думаю) Скотт Майєрс. Насправді я ніколи не чув, щоб хтось по-справжньому розумів правила C ++, сперечався щодо використання неподписаних.
Джеймс Канзе

2
@JamesKanze Насправді, в той же час я почув думку Stroustrup (конференція в Бостоні в 2008 році), Герб Саттер був там і не погодився з Bjarne на місці.
Неманья Трифунович

3
Тільки для завершення " unsignedзламано", одна з проблем полягає в тому, що коли C ++ порівнює типи подібного розміру з підписами та без підпису, він перетворюється на неподписаний, перш ніж проводити порівняння. Що призводить до зміни вартості. Перехід до підписаного не обов'язково буде набагато кращим; порівняння дійсно має відбуватися "так, як якщо б" обидва значення були перетворені на більш великий тип, який може представляти всі значення в обох типах.
Джеймс Канзе

1
@SteveJessop Я думаю, що ви повинні сприймати це в контексті повернення функції unsigned. Я впевнений, що у нього немає проблем із exp(double)поверненням значення більше MAX_INT:-). Але знову ж таки справжньою проблемою є неявні перетворення. int i = exp( 1e6 );цілком справедливий C ++. Stroustrup насправді запропонував знецінити неявні конверсії втрат в один момент, але комітет не зацікавився. (Цікаве питання: чи вважатимуться unsigned- intвтраченими. Я б вважав і unsigned-> intі int-> unsignedвтратою. Що б пройшло довгий шлях до досягнення unsignedОК
Джеймс Канзе

18

він більш інтуїтивний і легко зрозумілий. Це робить зрозумілий намір.

І це гарантує, що код не зламається, коли новий користувач може несвідомо пропустити {, }додаючи нову заяву коду.


Makes the intent clear+1, це, мабуть, найбільш стисла і точна причина.
Qix - МОНІКА ПОМИЛИЛА

13

Щоб додати до дуже розумних пропозицій, один із прикладів, з якими я стикався під час рефакторингу коду, де це стає критичним, був такий: я змінював дуже велику базу коду для переходу з одного API на інший. Перший API мав виклик встановити ідентифікатор компанії таким чином:

setCompIds( const std::string& compId, const std::string& compSubId );

тоді як для заміни були потрібні два дзвінки:

setCompId( const std::string& compId );
setCompSubId( const std::string& compSubId );

Я почав змінювати це, використовуючи регулярні вирази, які були дуже успішними. Ми також передали код через astyle , що насправді зробило його набагато більш читабельним. Потім, почасти через процес огляду, я виявив, що в деяких умовних обставинах це змінюється:

if ( condition )
   setCompIds( compId, compSubId );

До цього:

if ( condition )
   setCompId( compId );
setCompSubId( compSubId );

що явно не те, що потрібно було. Мені довелося повернутися до початку, зробіть це ще раз, трактуючи заміну як повністю всередині блоку, а потім вручну змінюючи все, що в кінцевому підсумку виглядає goofy (принаймні, це не було б неправильно.)

Я зауважую, що зараз у astyle є така опція, --add-bracketsяка дозволяє вам додавати дужки там, де їх немає, і я настійно рекомендую це, якщо ви коли-небудь опинитесь у такому ж становищі, як я.


5
Я одного разу побачив якусь документацію, яка мала чудову монету «Microsoftligent». Так, можна зробити суттєві помилки при глобальному пошуку та заміні. Це просто означає, що глобальний пошук і заміна повинні використовуватися розумно, а не мікрософт.
Піт Бекер

4
Я знаю, що це не моє посмертне виконання, але якщо ви збираєтеся робити заміну тексту у вихідному коді, то ви повинні робити це за тими самими правилами, що і для заміни тексту, яка добре встановлена мовою: макроси. Не слід писати макрос #define FOO() func1(); \ func2(); (з рядком рядка після зворотної косої риси), це ж стосується пошуку та заміни. З цього приводу я бачив, що "завжди використовуйте дужки", вдосконалений як правило стилю саме тому, що це рятує вас від обгортання всіх ваших макросів із кількома заявами do .. while(0). Але я не згоден.
Стів Джессоп

2
До речі, це "добре налагоджено", в тому сенсі, що японський спариш добре встановлений: я не кажу, що нам слід вийти з шляху використання макросів і заміни тексту, але я говорю, що коли ми робимо таке річ, ми повинні робити це так, як це працює, а не робити щось, що працює лише в тому випадку, якщо певне правило стилю вдало накладено на всю базу коду :-)
Стів Джессоп

1
@SteveJessop Можна також посперечатися на брекети та пояс. Якщо вам доведеться використовувати такі макроси (а ми це робили до C ++ і inline), то, ймовірно, вам слід націлитись на те, щоб вони працювали якомога більше, як функція, використовуючи do { ... } while(0)при цьому необхідний трюк (і багато додаткових дужок. Але це все-таки не буде не заважаю вам використовувати брекети скрізь, якщо це стиль будинку. (FWIW: Я працював у місцях із різними стилями будинку, охоплюючи всі розглянуті тут стилі. Ніколи не виявив жодної серйозної проблеми).
Джеймс Канзе

1
І я вважаю, чим більше стилів ви працювали, тим уважніше читаєте та редагуєте код. Тож навіть якщо у вас є перевага, яку найпростіше читати, ви все одно успішно читатимете інших. Я працював в компанії, де різні компоненти написані різними командами в різних стилях будинку, і правильне рішення - скаржитися на це в обідній залі без особливого ефекту, не намагатися створити глобальний стиль :-)
Стів Джессоп

8

Я використовую {}всюди, крім кількох випадків, коли це очевидно. Один рядок - один із випадків:

if(condition) return; // OK

if(condition) // 
   return;    // and this is not a one-liner 

Це може зашкодити вам, коли ви додасте якийсь метод перед поверненням. Відступ вказує на те, що повернення виконується, коли виконується умова, але воно буде повертатися завжди.

Інший приклад на C # з використанням statment

using (D d = new D())  // OK
using (C c = new C(d))
{
    c.UseLimitedResource();
}

що еквівалентно

using (D d = new D())
{
    using (C c = new C(d))
    {
        c.UseLimitedResource();
    }
}

1
Просто використовуйте коми у usingвиписці, і вам не доведеться :)
Ry-

1
@minitech Тут просто не працює - кома можна використовувати лише тоді, коли типи рівні, а не для неоднакових типів. Спосіб Лукаша це канонічний спосіб, IDE навіть форматує це по-різному (відзначте відсутність автоматичного відступу другого using).
Конрад Рудольф

8

Найдоречніший приклад, про який я можу придумати:

if(someCondition)
   if(someOtherCondition)
      DoSomething();
else
   DoSomethingElse();

З яким ifбуде elseпарний? Відступ означає, що зовнішній ifотримує else, але компілятор не буде бачити це; внутрішній if буде отримати else, і зовнішнійif не робить. Ви повинні знати, що (або побачити, як він веде себе таким чином в режимі налагодження), щоб з'ясувати, чому цей код може не піддавати вашим очікуванням. Це стає більш заплутаним, якщо ви знаєте Python; у такому випадку ви знаєте, що відступ визначає кодові блоки, тому ви очікуєте, що він буде оцінений відповідно до відступу. C #, однак, не дає пролітати навколо простору.

Тепер, сказане, я не особливо згоден з цим правилом "завжди використовувати дужки" на обличчі. Це робить код дуже вертикально галасливим, зменшуючи можливість швидко читати його. Якщо твердження:

if(someCondition)
   DoSomething();

... тоді слід писати саме так. Вислів "завжди використовувати дужки" звучить як "завжди оточують математичні операції з дужками". Це перетворило б дуже просту заяву a * b + c / dв ((a * b) + (c / d)), представляючи можливість пропуску великої дужки (бич багато чого кодера), і для чого? Порядок операцій добре відомий і добре виконується, тому круглі дужки є зайвими. Ви використовуєте дужки лише для виконання іншого порядку операцій, ніж зазвичай: застосовується, a * (b+c) / dнаприклад. Блок-брекети схожі; використовуйте їх для визначення того, що ви хочете робити у випадках, коли це відрізняється від типового, і не є "очевидним" (суб'єктивним, але, як правило, досить здоровим).


3
@AlexBrown ... що було саме моєю точкою. Правило, про яке йдеться в ОП, - "завжди використовувати дужки, навіть для одиночних рядків", з чим я не згоден з тієї причини, яку я зазначив. Кронштейни б допомогти з самим першим прикладом коду, тому що код не буде вести себе так , як це відступ; вам доведеться використовувати дужки, щоб з’єднати elseперше ifзамість другого. Видаліть заявку.
KeithS

5

Переглядаючи відповіді, ніхто не чітко вказав таку практику, яку я звикла, розповідаючи історію вашого коду:

int j = 0;
for (int i = 0 ; i < 100 ; ++i)
{
    if (i % 2 == 0)
    {
        j++;
    }
}

Стає:

int j = 0;
for (int i = 0 ; i < 100 ; ++i)
{
    if (i % 2 == 0) j++;
}

Поклавши j++на той самий рядок , що і якщо повинен сигналізувати будь-кому іншому, "я хочу тільки щоб цей блок колись збільшувався j" . З coursethis має сенс тільки , якщо рядок виглядає спрощено , наскільки це можливо, тому що поставивши крапку зупинки тут, як пери згадує, не збирається бути дуже корисним.

Насправді я щойно перебігав частину API Storm Twitter, яка має такий "сортування" коду в Java, ось фрагмент відповідного коду форми виконання коду на сторінці 43 цього слайд-шоу :

...
Integer Count = counts.get(word);
if (Count=null) count=0;
count++
...

У блоці циклу циклу є дві речі, тому я не став би вбудовувати цей код. Тобто ніколи :

int j = 0;
for (int i = 0 ; i < 100 ; ++i) if (i % 2 == 0) j++;

Це жахливо, і я навіть не знаю, чи працює це (за призначенням); не роби цього . Нові рядки та дужки допомагають розрізнити окремі, але пов’язані між собою фрагменти коду, аналогічно козі чи крапці з двокрапкою у прозі. Наведений вище блок є настільки ж поганим, що є дійсно довгим реченням з кількома застереженнями та деякими іншими твердженнями, які ніколи не порушують і не призупиняють виділяти окремі частини.

Якщо ви дійсно хочете телеграфувати когось іншого, це лише однолінійна робота, використовуйте термінальний оператор або ?:форму:

for (int i = 0 ; i < 100 ; ++i) (i%2 ? 0 : >0) j++;

Але це залежить від коду-гольфу, і я вважаю, що це не чудова практика (мені не зрозуміло, чи варто ставити j ++ на одну сторону :чи ні). NB: Я раніше не запускав потрійного оператора в C ++, не знаю, чи працює це, але він існує .

Коротко:

Уявіть, як ваш читач (тобто особа, що підтримує код) інтерпретує вашу історію (код). Зробити це максимально зрозумілим для них. Якщо ви знаєте, що початківець кодер / студент це підтримує, можливо, навіть залиште їх якомога більше {}, тільки щоб вони не плуталися.


1
(1) Якщо розміщення висловлювання в одному рядку робить його менш читабельним, не більше. Особливо прості думки, як приріст, легко не помітити. Поставте їх на нову лінію. (2) Звичайно, ви можете поставити forцикл на одну лінію, чому це не повинно працювати? Це працює з тієї ж причини, що ви можете опустити брекети; новий рядок просто не має значущого значення на C ++. (3) Ваш приклад умовного оператора, окрім жахливого, є недійсним C ++.
Конрад Рудольф

@KonradRudolph дякую, я трохи іржавий на C ++. Я ніколи не говорив, що (1) є більш читабельним, але це би сигналізувало про те, що цей фрагмент коду мав на увазі онлайн-рядок. (2) Мій коментар був тим більше, що я не зміг би його прочитати і знати, що він працює, будь то чи за призначенням; це приклад того, що не потрібно робити з цієї причини. (3) Дякую, я давно не писав C ++. Я зараз це виправлю.
Pureferret

2
Крім того, якщо більше одного виразу в одному рядку ускладнює налагодження коду. Як ви ставите точку розриву на другу вираз у цьому рядку?
Piotr Perak

5

Тому що, коли у вас є дві заяви без {}цього, проблему легко пропустити. Припустимо, що код виглядає приблизно так.

int error = 0;
enum hash_type hash = SHA256;
struct hash_value *hash_result = hash_allocate();

if ((err = prepare_hash(hash, &hash_result))) != 0)
    goto fail;
if ((err = hash_update(&hash_result, &client_random)) != 0)
    goto fail;
if ((err = hash_update(&hash_result, &server_random)) != 0)
    goto fail;
if ((err = hash_update(&hash_result, &exchange_params)) != 0)
    goto fail;
    goto fail;
if ((err = hash_finish(hash)) != 0)
    goto fail;

error = do_important_stuff_with(hash);

fail:
hash_free(hash);
return error;

Це добре виглядає. Проблему з цим дійсно легко пропустити, особливо коли функція, що містить код, значно більша. Проблема полягає в тому, що вона goto failпрацює беззастережно. Ви можете легко уявити, як це засмучує (змушуючи запитати, чому останній hash_updateзавжди не вдається, адже все виглядає добре у hash_updateфункції).

Однак це не означає, що я додаю {}всюди (на мою думку, бачити {}скрізь дратує). Хоча це може спричинити проблеми, воно ніколи не робилося для моїх власних проектів, оскільки мій особистий стиль кодування забороняє умовні умови, {}коли вони не знаходяться в одній лінії (так, я згоден, що мій стиль кодування нетрадиційний, але мені це подобається, і мені використовувати стиль коду проекту під час участі в інших проектах). Це робить наступний код прекрасним.

if (something) goto fail;

Але не наступний.

if (something)
    goto fail;

Саме так. Просто не ставте (абсолютно непотрібний) новий рядок + відступ, і ви повністю оминаєте це питання, що всі завжди так швидко вирішують питання.
Олександр - Відновіть Моніку

4

Це робить ваш код більш читабельним, чітко визначаючи сферу циклів і умовних блоків. Це також рятує вас від випадкових помилок.


4

wrt 6: Це безпечніше, оскільки видалення нульового вказівника - неоперативне. Тож якщо ви випадково двічі пройдете цей шлях, ви не призведете до пошкодження пам’яті, щоб звільнити пам'ять, яка є вільною або виділена на щось інше.

Це найбільше питання зі статичними об'єктами файлових файлів та одинарними кнопками, які не дуже чітке життя, і, як відомо, їх відтворили після їх знищення.

У більшості випадків ви можете уникнути потреби в цьому, використовуючи auto_ptrs


6
Якщо вам трапляється пройти цей шлях двічі, у вас виникла помилка програмування. Встановлення покажчика на нуль, щоб зробити цю помилку менш шкідливою, не вирішує основну проблему.
Піт Бекер

1
Погодився, але я бачив це рекомендовано і раніше, і я вважаю, що це в деяких професійних стандартах програмування. Я коментував більше того, чому професор плаката придумав це, а не коли це було добре
Том Таннер

2
Слідом за тим, що сказав Піт Бекер: це не вирішує основну проблему, але може замаскувати її. (Є випадки, коли ви б встановили вказівник NULLпісля видалення його. Якщо NULLправильне значення має покажчик у цих умовах; наприклад, вказівник вказує на кешоване значення та NULLвказує на недійсний кеш. Але коли ви бачите, хтось встановлює вказівник на NULLостанній рядок у деструкторі, вам цікаво, чи знає він C ++.)
Джеймс Канзе

4

Мені подобається прийнята відповідь Лучіана, адже я навчився тяжкого способу його правильності, тому я завжди використовую дужки, навіть для однорядних блоків. Однак особисто я роблю виняток, коли пишуть фільтр, як ви у своєму прикладі. Це:

int j = 0;
for (int i = 0 ; i < 100 ; ++i)
{
    if (i % 2 == 0)
    {
        j++;
    }
}

виглядає захаращеним на мене. Він відокремлює цикл for і цикл if на окремі дії, коли дійсно ваш намір є однією дією: підрахувати всі цілі числа, що поділяються на 2. Більш виразною мовою це може бути записано щось на кшталт:

j = [1..100].filter(_%2 == 0).Count

У мовах, у яких відсутня закриття, фільтр не може бути виражений в одному операторі, але повинен бути циклом for, за яким слід оператор if. Однак це все ще одна дія на увазі програміста, і я вважаю, що це повинно бути відображено в коді, як-от так:

int j = 0;
for (int i = 0 ; i < 100 ; ++i)
  if (i % 2 == 0)
{
    j++;
}

7
Мені подобається, як всім вдається ігнорувати for (int i = 0; i < 100; i += 2);заради продовження аргументації щодо відступу ;-) Мабуть, існує ціла окрема боротьба з битвою, як "найкраще" висловити логіку "для кожного iв певному діапазоні з певним властивістю" в C ++ без циклу, використовуючи комбінацію кошмарів стандартних алгоритмів filter_iteratorта / або counting_iterator.
Стів Джессоп

1
Крім того, якби у нас це було, ми могли б не погодитися з тим, як відступити отримане масове єдине твердження.
Стів Джессоп

2
@Steve, проте це лише приклад. Існує безліч законних способів використання шаблону. Очевидно, якщо ви хочете порахувати числа від 1 до 100, які поділяються на 2, все, що вам потрібно зробити, - це 100/2.
MikeFHay

2
Звичайно, я знаю, тому я абстрагувався на "для кожного iв певному діапазоні з певною властивістю". Просто так, звичайно на SO, люди дуже швидко ігнорують актуальне питання на користь зовсім іншого підходу до наведеного прикладу. Але відступ важливий , тому ми не робимо ;-)
Стів Джессоп

4

Одним із варіантів, що допомагає запобігти описаним вище помилкам, є вказівка ​​того, що ви хочете статися, коли ви не використовуєте брекети. Значно важче не помітити помилки при спробі змінити код.

if (condition) doSomething();
else doSomethingElse();

if (condition) doSomething();
    doSomething2(); // Looks pretty obviously wrong
else // doSomethingElse(); also looks pretty obviously wrong

5
Другий варіант призведе до помилки компіляції, оскільки elseвона не пов'язана з if.
Лучіан Григоре

Однією не настільки помітною проблемою вбудованого файлу є те, що більшість IDE за замовчуванням змінюють його на відступний стиль, використовуючи утиліту автоформату.
Honza Brabec

@Honza: однак це дуже заряджене політичне питання. Якщо ми співпрацюємо на основі коду, ми або мусимо використовувати один і той же стиль відступу до кожної останньої деталі, або ми повинні погодитись не форматувати існуючий код "просто тому". Якщо колишній тоді узгоджений стиль все-таки міг би включати це, але вам доведеться або налаштувати свій IDE на його повагу, або не використовувати автоформат. Погоджуючись, що загальний формат - це "будь-який мій автоформат IDE", це все добре, якщо ми всі використовуємо той самий IDE назавжди, не дуже добре в іншому випадку.
Стів Джессоп

3

Якщо ви компілятор, це не має ніякого значення. Обидва однакові.

Але для програмістів перший є більш зрозумілим, легким для читання та менш схильним до помилок.


2
Окрім відкриття {на власній лінії, все одно.
Роб

3

Ще один приклад додавання фігурних брекетів. Одного разу я шукав помилку і знайшов такий код:

void SomeSimpleEventHandler()
{
    SomeStatementAtTheBeginningNumber1;
    if (conditionX) SomeRegularStatement;
    SomeStatementAtTheBeginningNumber2;
    SomeStatementAtTheBeginningNumber3;
    if (!SomeConditionIsMet()) return;
    OtherwiseSomeAdditionalStatement1;
    OtherwiseSomeAdditionalStatement2;
    OtherwiseSomeAdditionalStatement3;
}

Якщо ви прочитаєте метод по черзі, ви помітите, що в методі є умова, яка повертається, якщо це неправда. Але насправді це схоже на 100 інших простих обробників подій, які встановлюють деякі змінні на основі деяких умов. І ось одного разу приходить Швидкий Кодер і додає додаткову заяву змінної настройки в кінці методу:

{
    ...
    OtherwiseSomeAdditionalStatement3;
    SetAnotherVariableUnconditionnaly;
}

Як результат, SetAbodyVariableUnconditionnaly виконується, коли SomeConditionIsMet (), але швидкий хлопець цього не помічає, оскільки всі рядки майже однакові за розміром, і навіть коли умова повернення вертикально відрізана, це не так помітно.

Якщо умовне повернення відформатоване так:

if (!SomeConditionIsMet())
{
    return;
}

це помітно і Швидкий Кодер знайде його з першого погляду.


Якщо вашому швидкому кодеру не можна заважати виявити синтаксичний returnоператор у тілі функції перед тим, як додати щось до нього, ви не повинні дозволяти швидкому кодеру наближатися до вашого коду. Ви не зупините такого хлопця, щоб обходити ваш код, додаючи брекети.
cmaster - відновити моніку

@cmaster Він більше не працює з нами. У будь-якому випадку, виділення синтаксису добре, але пам’ятайте, що є люди, які не бачать чітко (я бачив навіть повідомлення сліпого програміста минулого року).
Артемікс

2

Я вважаю, що перший є зрозумілим, а потім другий. Це дає відчуття закриття інструкцій, з невеликим кодом добре, коли код стає складним, {...}допомагає дуже багато, навіть якщо він є endifабоbegin...end

//first
int j = 0;
for (int i = 0 ; i < 100 ; ++i)
{
    if (i % 2 == 0)
    {
        j++;
    }
}


//second
int j = 0;
for (int i = 0 ; i < 100 ; ++i)
    if (i % 2 == 0)
        j++;
i++;

1

Найкраще встановити вказівник на NULL, коли ви закінчили його.

Ось приклад, чому:

Клас A робить наступне:

  1. Виділяє блок пам'яті
  2. Потім через деякий час він видаляє цей блок пам'яті, але не встановлює покажчик на NULL

Клас В робить наступне

  1. Виділяє пам'ять (і в цьому випадку трапляється надавати той самий блок пам'яті, який був видалений класом A.)

На даний момент і клас A, і клас B мають вказівники, що вказують на один і той же блок пам'яті, що стосується класу A, то цього блоку пам'яті не існує, оскільки він закінчений ним.

Розглянемо таку проблему:

Що робити, якщо в класі A сталася логічна помилка, що призвело до того, що вона записується в пам'ять, яка тепер належить до класу B?

У цьому конкретному випадку ви не отримаєте помилки з виключенням доступу, оскільки адреса пам’яті є законною, і весь час клас A фактично пошкоджує дані класу B.

Зрештою, клас B може вийти з ладу, якщо він зіткнеться з несподіваними значеннями, і коли він стане крахом, швидше за все, ви витратите досить довгий час на полювання на цю помилку в класі В, коли проблема знаходиться в класі А.

Якби ви встановили видалений вказівник пам'яті на NULL, ви отримали б помилку виключення, як тільки будь-які логічні помилки класу A намагалися записати на покажчик NULL.

Якщо ви турбуєтесь про логічну помилку з подвійним видаленням, коли покажчики NULL вдруге, тоді додайте ствердження для цього.

Також: Якщо ви збираєтесь відмовитися від голосування, будь ласка, поясніть.


2
Якщо була логічна помилка, її слід виправити, а не маскувати її.
uınbɐɥs

@Barmar, OP каже ... 6. Встановіть покажчик на NULL після видалення - захист подвійного видалення // не погано. Деякі люди відповіли, що не встановлюють його на Null, і я кажу, чому його слід встановити на NULL, яка частина 6. моя відповідь на встановлення NULL не відповідає 6?
Джон

1
@Shaquin, А як ви пропонуєте в першу чергу знайти ці логічні помилки? Після встановлення змінної вказівника на NULL після видалення пам'яті. Будь-яка спроба посилання на вказівник NULL призведе до аварійного налагодження на лінії, в якій була зроблена ваша незаконна спроба. Ви можете простежити назад і подивитися, де була логічна помилка, і виправити проблему. Якщо ви не встановите змінну вказівника на NULL після того, як ви видалили пам'ять, ваша незаконна спроба записати цю видалену пам'ять через помилки логіки UNAWARE може закінчитися успішною, і тому в цій точці не виходить з ладу. Це не маскування.
Джон

1

Завжди мати фігурні брекети - це дуже просте і надійне правило. Однак код може виглядати неелегантним, коли є багато брекетів. Якщо правила дозволяють опускати фігурні фігурні дужки, то повинні бути більш детальні правила стилю та більш досконалі інструменти. В іншому випадку це може призвести до хаотичного та заплутаного (не елегантного) коду. Тому дивитись єдине правило стилю, окремо від решти стильових посібників та інструментів, можливо, безрезультатно. Я лише наведу кілька важливих деталей про це правило №3, про які навіть не було сказано в інших відповідях.

Перша цікава деталь полягає в тому, що більшість прихильників цього правила погоджуються порушувати його у випадку else. Іншими словами, вони не вимагають перегляду такого коду:

// pedantic rule #3
if ( command == Eat )
{
    eat();
}
else
{
    if ( command == Sleep )
    {
        sleep();
    }
    else
    {
        if ( command == Drink )
        {
            drink();
        }
        else
        {
            complain_about_unknown_command();
        }
    }
}

Натомість, якщо вони це бачать, вони можуть навіть запропонувати написати так:

// not fully conforming to rule #3
if ( command == Eat )
{
    eat();
}
else if ( command == Sleep )
{
    sleep();
}
else if ( command == Drink )
{
    drink();
}
else
{
   complain_about_unknown_command();
}

Це технічно є порушенням цього правила, оскільки між elseі між ними немає фігурних дужок if. Така подвійність правила виникає, коли намагатися автоматично застосувати його до кодової бази за допомогою бездумного інструменту. Дійсно, навіщо сперечатися, просто дозвольте автоматично застосувати стиль.

Друга деталь (яку також часто забувають прихильники цього правила) полягає в тому, що помилки, які можуть статися, ніколи не бувають лише через порушення цього правила №3. Насправді, вони майже завжди пов’язані з порушенням правила №1 (з яким ніхто не сперечається). Знову ж таки з точки зору автоматичних інструментів, не важко зробити інструмент, який негайно скаржиться на порушення правила №1, і тому більшість помилок можна вчасно виявити.

Третя деталь (яку часто забувають опоненти цього правила) - заплутаний характер порожнього висловлювання, представленого одиничною крапкою з комою. Більшість розробників з певним досвідом рано чи пізно плутаються через єдину неправильну крапку з комою або порожню заяву, яка пишеться за допомогою крапки з комою. Два фігурні дужки замість однієї крапки з комою візуально легше помітити.


1

Мушу визнати, що не завжди використовуйте {}для однорядкових, але це хороша практика.

  • Скажімо, ви пишете код без дужок, який виглядає приблизно так:

    для (int i = 0; i <100; ++ i) для (int j = 0; j <100; ++ j) DoSingleStuff ();

А через деякий час ви хочете додати в jцикл деякі інші речі, і ви просто зробите це, вирівнюючи і забудьте додати дужки.

  • Діалокація пам'яті відбувається швидше. Скажімо, у вас великий обсяг і створюйте великі масиви всередині (без того, newщоб вони знаходилися в стеці). Ці масиви видаляються з пам'яті одразу після того, як ви залишите область застосування. Але можливо, що ви використовуєте цей масив в одному місці, і він деякий час буде знаходитись у стеці та бути якимось сміттям. Оскільки стек має обмежений і досить невеликий розмір, можна перевищити розмір стека. Тому в деяких випадках краще написати, {}щоб не допустити цього. ПРИМІТКА це не для одного рядка, а для таких ситуацій:

    if (...) {// SomeStuff ... {// у нас немає, якщо, в той час, і т.д. // SomeOtherStuff} // SomeMoreStuff}

  • Третій спосіб його використання аналогічний другому. Це просто не зробити стек чистішим, а відкрити деякі функції. Якщо ви користуєтесь mutexдовгими функціями, краще заблокувати та розблокувати безпосередньо перед доступом до даних та відразу після закінчення читання / написання. ПРИМІТКА Цей спосіб використовується, якщо у вас є свій власний classабо structз constructorі destructorдля блокування пам'яті.

  • Що ще:

    if (...) if (...) SomeStuff (); else SomeOtherStuff (); // переходить до другого if, але вирівнювання показує, що це на першому ...

Загалом, я не можу сказати, який найкращий спосіб завжди використовувати {} для однієї лінії, але це не є поганим.

ВАЖЛИВО ЗМІСТ Якщо ви пишете компілюючі дужки коду для одного рядка, це нічого не робить, але якщо ваш код буде інтерпретований, він сповільнює код дуже незначно. Дуже трохи.


1

Існує ряд можливих способів написання контрольних заяв; певні комбінації з них можуть співіснувати, не погіршуючи розбірливості, але інші комбінації спричинять проблеми. Стиль

if (condition)
  statement;

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

if (condition)
{
  statement;
  statement;
}

тоді буде візуально очевидно, які ifоператори керують одним рядком, а які керують кількома рядками. Якщо, однак, багаторядкові ifтвердження записуються як:

if (condition) {
  statement;
  statement;
}

то ймовірність того, що хтось спробує розширити ifконструкції з одним оператором без додавання необхідних дужок, може бути набагато вище.

Оператор-один-наступний рядок ifтакож може бути проблематичним, якщо база даних кодів істотно використовує форму

if (condition) statement;

Моє власне вподобання полягає в тому, що наявність висловлювання у власному рядку, як правило, підвищує розбірливість, за винятком випадків, коли є багато ifвисловлювань із подібними контрольними блоками, наприклад

if (x1 > xmax) x1 = xmax;
if (x1 < xmin) x1 = xmin;
if (x2 > xmax) x2 = xmax;
if (x2 < xmin) x2 = xmin;
etc.

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.