Обслуговування розумне, чи "ще поки" без втручання брекетів вважається безпечним?


26

Невже else whileбез втручання брекетів вважається "безпечним" технічне обслуговування?

Написання if-elseкоду без дужок, як нижче ...

if (blah)
    foo();
else
    bar();

... несе ризик, оскільки відсутність дужок дозволяє дуже легко змінити значення коду ненавмисно.

Однак нижче також ризиковано?

if (blah)
{
    ...
}
else while (!bloop())
{
    bar();
}

Або else whileбез втручання брекетів вважається "безпечним"?


20
мені else whileвиглядає прикро. Я б користувався else { while (condition) { ... } }.
Йоахім Зауер

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


12
Чесно кажучи, це дає мені повзання. ifоцінюється лише один раз, але whileпозначає цикл, тому з'єднання обох дає мені необгрунтоване відчуття, що ifце частина циклу ... якось ...
user281377

4
А що, якщо в elseпункті ви хочете зробити while і зробити щось більше? Просто використовуйте брекети, будь ласка.
Карлос Кампдеррос

Відповіді:


57

Це нагадує мені цей код:

if ( ... ) try {
..
} catch (Exception e) {
..
} else {
...
}

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


18
Хороший приклад. Який жахливий спосіб написати це.
Лев

4
Ого, ця відповідь смішно переконлива!
Мехрдад

Ви можете легко налаштувати сучасні IDE для автоматичного форматування коду при збереженні - включаючи вставлення дужок та виправлення відступів. Тож це лише половина аргументу. Належне відступ це не створювало б проблем для читабельності, існують чи брекети чи ні.
Ганс-Пітер Штерр

55

Можливо, це тому, що я навчився моїй торгівлі (назад, коли), використовуючи метод діаграми структури Джексона Субстанції , але я підписуюся на думку, що єдиний правильний необмежений термін після ifабо else- це наступний if(тобто дозволяючи else ifсходи)

Все інше (не призначене для каламбуру) залишає потенціал для непорозуміння та / або обслуговування обслуговування. Це головний аспект ідеї ОП - "небезпечний".

Я також був би дуже задумливий щодо того, щоб включити while()ту саму лінію, що і те else- незалежно від того, чи це зроблено чи ні. Мені це правильно не читається ... відсутність зайвих відступів масок, що це elseпункт. А недостатня ясність створює непорозуміння (див. Вище).

Тож у прикладі я б настійно радив / рекомендував (і наполягаю на своїй команді) щодо:

if ( blah )
{
    ...
}
else
{
    while ( !bloop() )
    {
        bar();
    }
}

Звичайно, я також сподівався б побачити відповідні коментарі.

- Редагувати -

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


2
Я погоджуюся, якщо це єдиний правильний термін, який слід за іншим. Якби він був, else whileя, мабуть, навіть не помітив, що в швидкому проскакуванні коду з'явився цикл, особливо якщо умова, яку я шукав, була задоволена if.
Дрейк Кларріс

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

2
@JeffDavis це хороший улов. "Легше читати" - типове запрошення до марної святої війни. Я, наприклад, віддаю перевагу брекетів, але не через невідповідне сміття "легше читати" (для мене, наприклад, саме навпаки), а тому, що важче порушити подальше обслуговування коду. До речі, ОП проголосувало це краще у їхньому питанні: чи else whileбез втручання брекетів вважається "безпечним" ?
гнат

@JeffDavis - Я знаю, що цій темі вже два роки, але нещодавно Apple виявила, чому не використовувати брекети - це не дуже гарна ідея andrewbanks.com/…
Ендрю,

@Andrew До речі, мова Swift від Apple зараз прямо забороняє однолінійний контроль потоку. Ця помилка може бути однією з причин цього зробити.
Султан

6

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

    if(blah)
    {
     ....
    }
    else
    {
       while(!bloop()
       {
        bar;
       }
    }

6

Я видобув би метод і встиг

if ( blah )
{
    ...
}
else
{
   newMethod();
}

Див. Підхід "метод вилучення", пояснений на веб-сайті каталогу Refactoring :

У вас є фрагмент коду, який можна згрупувати.

Перетворіть фрагмент у метод, ім'я якого пояснює призначення методу.

void printOwing() {
    printBanner();

    //print details
    System.out.println ("name:    " + _name);
    System.out.println ("amount    " + getOutstanding());
}

                                                                                                         http://www.refactoring.com/catalog/arrow.gif

void printOwing() {
    printBanner();
    printDetails(getOutstanding());
}

void printDetails (double outstanding) {
    System.out.println ("name:    " + _name);
    System.out.println ("amount    " + outstanding);
}

Залежить ... якщо, наприклад, цикл використовував дані рівня рівня функцій, тепер вам доведеться більше цих даних для модульного (або класового, якщо використовуєте рівня C ++). І якщо лише невеликий фрагмент коду, ви використовуєте тривіальні методи. Але іноді, залежно від обставин, я погодився б.
Андрій

1
+1 Smart C ++ компілятори можуть вбудовувати функцію. У середовищі .Net невеликі функції краще завдяки JIT.
робота

4

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

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

if ( blah )
{
    ...
}
else
{
    while ( !bloop() )
    {
        bar();
    }
}

Добре застосовувати код у блоках. Це робить його простішим і легшим для розуміння та налагодження.


4

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

Однак, коли це стає безладним, коли ви вкладете, якщо / else зациклює деякі з дужками, а деякі без. Хоча петля посеред усіх тих спагетті! Я працював з кодом, що погано, і це кошмар, щоб налагодити і зрозуміти. Це випливає з першого пункту, це добре, коли він залишається простим, і ви цим задоволені, але потім приходять інші програмісти і додають до нього речі, ймовірно, якщо це ще не в циклі while. Якщо в першу чергу це написано чисто, то шансів на це трапиться менше.

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

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


3

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

if (...)
   foo();
else while(...)
   bar();

... Я насправді вважаю це else while(...)чудово " " читабельним! Він навіть читається як звичайна англійська! Але я думаю, що всім це буде дивно, тому що це сказати незвично.

Врешті-решт, ми всі схильні робити це ідіотом, хоча дужками ... бо, ну, ви знаєте.


3
це буде особливо читабельним після того, як деякі невинні аніматори змінили else while(...) bar();щось на кшталт else while(...) foobar(); bar();:)
gnat

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

2
"Завжди кодуйте так, ніби людина, яка підтримуватиме ваш код, - це жорстокий психопат, який знає, де ви живете". ( Alan Braggins )
комар

1
Ну, все зводиться до того, що ви вважаєте, що найглупіший рівень того, хто працює над вашим кодом, був би. Я стверджую, що якщо ваш "технічний супровідник" заплутається в цих чотирьох рядках коду ... тоді у вас є величезна проблема. І якщо це жорстокий психолог, у вас є двоє. ;)
dagnelies

1
якщо - добре, посилання, на яке я згадуюсь вище, розширила версію цієї цитати: Програміст 1: "Тут є приємна цитата -" Завжди кодуйте так, ніби людина, яка підтримуватиме ваш код, - жорстокий психопат, який знає, де ви живете ". . Програміст 2: (переглядає технічного обслуговування) "Що ви маєте на увазі" ніби "?"
гнат

2

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

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

Розміщення брекетів, ймовірно, викликає більше аргументів, ніж все, що виходить за рамки (або, можливо, включаючи) релігії!
Андрій

Домовились. Відредагую мою відповідь, щоб наголосити на їхньому існуванні, а не на позиції.
Цветомир Димитров

2

Що настільки не так з брекетами, що так багато людей намагаються уникати їх написання?

Яку проблему точно else whileвирішує?

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

Цитуючи філософію Unix:

Правило ясності: Ясність краща за розум.

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


1

У цьому немає нічого поганого

if (blah)
    foo();
else
    bar();

так само, як немає нічого поганого

if (blah) foo(); else bar();

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

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


до того ж, я вже бачив цей код:

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

і це написав сам стандарт кодування нацист (який наполягав на дужках для всього).


1

Сучасні IDE можна легко налаштувати на переформатування (включаючи видалення або додавання непотрібних дужок) та / або повторне введення коду під час збереження файлу. Таким чином, ваш приклад автоматично виглядав би, наприклад

if (blah) {
  blub();
} else
  while (!bloop()) {
    bar();
  }

Відступ завжди робить гніздування легко помітним, навіть без непотрібних брекетів. Отже, якщо вам вдасться застосувати такі налаштування IDE, я не бачу ніякого ризику.

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

if (blah) blub();
else while (!bloop()) bar();

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

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