Що так погано з goto, коли він використовується для цих очевидних і релевантних випадків?


40

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

У мене є IP, де мені потрібно перевірити, чи є в списку IP-адреси, а потім приступити до коду, інакше киньте виняток.

<?php

$ip = '192.168.1.5';
$ips = [
    '192.168.1.3',
    '192.168.1.4',
    '192.168.1.5',
];

foreach ($ips as $i) {
    if ($ip === $i) {
        goto allowed;
    }
}

throw new Exception('Not allowed');

allowed:

...

Якщо я не використовую, gotoто мені доведеться використовувати якусь змінну на кшталт

$allowed = false;

foreach ($ips as $i) {
    if ($ip === $i) {
        $allowed = true;
        break;
    }
}

if (!$allowed) {
    throw new Exception('Not allowed');
}

Моє запитання: що ж такого поганого, gotoколи він використовується для таких очевидних і незмінно відповідних випадків?


Коментарі не для розширеного обговорення; ця розмова переміщена до чату .
maple_shaft

Відповіді:


120

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

if (!contains($ips, $ip)) throw new Exception('Not allowed');

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

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

$list_contains_ip = undef;        # STATE: we don't know yet

foreach ($ips as $i) {
  if ($ip === $i) {
      $list_contains_ip = true;   # STATE: positive
      break;
  }
                                  # STATE: we still don't know yet, huh?                                                          
                                  # Well, then...
  $list_contains_ip = false;      # STATE: negative
}

if (!$list_contains_ip) {
  throw new Exception('Not allowed');
}

де $list_contains_ipє вашою єдиною змінною стану або неявно:

                             # STATE: unknown
foreach ($ips as $i) {       # What are we checking here anyway?
  if ($ip === $i) {
    goto allowed;            # STATE: positive
  }
                             # STATE: unknown
}
                             # guess this means STATE: negative
throw new Exception('Not allowed');

allowed:                     # Guess we jumped over the trap door

Як бачите, в конструкції GOTO є неоголошена змінна стан. Це само по собі не є проблемою, але ці змінні стану схожі на камінчики: носити одну із них не важко, носіння повного з ними сумки змусить вас потіти. Ваш код не залишиться колишнім: наступного місяця вам буде запропоновано розмежувати приватні та загальнодоступні адреси. Через місяць після цього ваш код повинен підтримувати діапазони IP. Наступного року хтось попросить вас підтримати адреси IPv6. У найкоротші терміни ваш код буде виглядати так:

if ($ip =~ /:/) goto IP_V6;
if ($ip =~ /\//) goto IP_RANGE;
if ($ip =~ /^10\./) goto IP_IS_PRIVATE;

foreach ($ips as $i) { ... }

IP_IS_PRIVATE:
   foreach ($ip_priv as $i) { ... }

IP_V6:
   foreach ($ipv6 as $i) { ... }

IP_RANGE:
   # i don't even want to know how you'd implement that

ALLOWED:
   # Wait, is this code even correct?
   # There seems to be a bug in here.

І хто повинен налагодити цей код, проклинає вас і ваших дітей.

Dijkstra вважає так:

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

І тому GOTO вважається шкідливим.


22
Це $list_contains_ip = false;твердження здається недоречним
Бергі

1
Мішок, повний камінчиків, легко, у мене є зручний мішок для їх тримання. : p
whatsisname

13
@Bergi: Ти маєш рацію. Це показує, як легко зіпсувати ці речі.
wallenborn

6
@whatsisname Цей мішок називається функцією / класом / пакетом для їх зберігання. використовувати готос - це як жонглювати ними та викидати мішок.
Falco

5
Мені подобається цитата з Dijkstra, я не чув, щоб це було так, але це справді хороший момент. Замість того, щоб мати потік, який знаходиться майже вгорі, знизу, раптом у вас з’являється щось, що може стрибати по всій сторінці навмання. Коротко кажучи, це дуже вражає.
Білл К

41

Існує кілька законних випадків використання для GOTO. Наприклад, для керування помилками та очищення в C або для впровадження деяких форм державних машин. Але це не один із таких випадків. Другий приклад - більш читаний IMHO, але ще читабельніше було б витягнути цикл в окрему функцію, а потім повернутися, коли знайдете відповідність. Ще краще було б (у псевдокоді, я не знаю точного синтаксису):

if (!in_array($ip, $ips)) throw new Exception('Not allowed');

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

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


5
@jameslarge it's easier to write good optimizing compilers for "structured" languages.Догляд докласти ? Як зустрічний приклад, люди з Рустом представили MIR , проміжне представлення у компіляторі, яке спеціально замінює петлі, триває, розбиває та інше з gotos, оскільки це простіше перевірити та оптимізувати.
8bittree

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

8
Крім того, IMO, емуляція gotoз щурами гніздо прапорів та умовних умов (як у другому прикладі ОП) набагато менше читається, ніж джути з використанням a goto.

3
@ 8bittree: Структуроване програмування призначене для вихідної мови, а не цільової мови компілятора. Цільовою мовою для власних компіляторів є інструкції процесора, які, очевидно, не "структуровані" в мові програмування.
Роберт Харві

4
@ 8bittree Відповідь на ваше запитання щодо MIR знаходиться у посиланні, яке ви надали: "Але прекрасно мати таку конструкцію в MIR, оскільки ми знаємо, що вона буде використовуватися лише певними способами, такими як вираження циклу або перерва. . " Іншими словами, оскільки goto заборонено в Rust, вони знають, що це структуровано і проміжна версія з gotos теж є. Зрештою, код повинен спуститися до goto, як машинні команди. Що я отримую від вашого посилання, це те, що вони просто додають покроковий крок у перетворенні з мови високого рівня на низький рівень.
JimmyJames

17

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

Припустимо такий фрагмент коду:

       i = 4;
label: printf( "%d\n", i );

Яке значення надрукується i? Коли він друкується? Поки ви не будете обліковувати кожен екземпляр goto labelсвоєї функції, ви не можете знати. Проста наявність цієї мітки руйнує вашу здатність налагоджувати код простим оглядом. Для невеликих функцій з однією або двома гілками не велика проблема. Для не малих функцій ...

Ще на початку 90-х нам дали купу коду С, який наніс 3d графічний дисплей і сказав, щоб змусити його працювати швидше. Це було лише близько 5000 рядків коду, але все це було main, і автор використав близько 15 gotoрозгалужень в обох напрямках. Це було поганим кодом для початку, але присутність цих людей gotoзробила це набагато гірше. Моєму співробітникові знадобилося близько 2 тижнів, щоб розгадати потік контролю. Ще краще, що вони gotoпризвели до того, що код настільки щільно поєднався з самим собою, що ми не могли вносити жодних змін, нічого не порушуючи.

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

Зрештою, ми дали замовникові два варіанти - давайте перепишемо всю справу з нуля, або купимо швидше обладнання.

Вони купували швидше обладнання.

Правила Bode щодо використання goto:

  1. Гілка лише вперед;
  2. Не обминайте керуючі структури (тобто, не розгалужуйте в тіло ifабо forабо whileзаяву);
  3. Не використовуйте gotoзамість структури управління

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

EDIT

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

T ***myalloc( size_t N, size_t M, size_t P )
{
  size_t i, j, k;

  T ***arr = malloc( sizeof *arr * N );
  for ( i = 0; i < N; i ++ )
  {
    arr[i] = malloc( sizeof *arr[i] * M );
    for ( j = 0; j < M; j++ )
    {
      arr[i][j] = malloc( sizeof *arr[i][j] * P );
      for ( k = 0; k < P; k++ )
        arr[i][j][k] = initial_value();
    }
  }
  return arr;
}

Тепер у нас є проблема - що робити, якщо один із mallocдзвінків не завершиться посередині? Навряд чи така подія може бути, ми не хочемо повертати частково виділений масив, а також не хочемо просто виконувати функцію з помилкою; ми хочемо прибрати за собою і розмістити будь-яку частково виділену пам'ять. Мова, яка кидає виняток на поганий аллокал, це досить просто - ви просто пишете обробник винятків, щоб звільнити те, що вже було виділено.

У C у вас немає структурованої обробки винятків; ви повинні перевірити значення повернення кожного mallocдзвінка і вжити відповідних дій.

T ***myalloc( size_t N, size_t M, size_t P )
{
  size_t i, j, k;

  T ***arr = malloc( sizeof *arr * N );
  if ( arr )
  {
    for ( i = 0; i < N; i ++ )
    {
      if ( !(arr[i] = malloc( sizeof *arr[i] * M )) )
        goto cleanup_1;

      for ( j = 0; j < M; j++ )
      {
        if ( !(arr[i][j] = malloc( sizeof *arr[i][j] * P )) )
          goto cleanup_2;

        for ( k = 0; k < P; k++ )
          arr[i][j][k] = initial_value();
      }
    }
  }
  goto done;

  cleanup_2:
    // We failed while allocating arr[i][j]; clean up the previously allocated arr[i][j]
    while ( j-- )
      free( arr[i][j] );
    free( arr[i] );
    // fall through

  cleanup_1:
    // We failed while allocating arr[i]; free up all previously allocated arr[i][j]
    while ( i-- )
    {
      for ( j = 0; j < M; j++ )
        free( arr[i][j] );
      free( arr[i] );
    }

    free( arr );
    arr = NULL;

  done:
    return arr;
}

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


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

якщо вам потрібно вийти з глибоко вкладеного циклу, вам просто потрібно зробити цю петлю ще однією функцією і повернутися
bunyaCloven

6
Як колись хтось підсумував це для мене: "Це не проблема переходу, це проблема, яка виходить". Як фахівець з оптимізації програмного забезпечення, я погоджуюся, що неструктурований потік управління може кидати компілятори (і люди!) Для циклу. Я одного разу провів години, розшифровуючи просту машину держави (чотири з п’яти станів) у функції BLAS, яка використовувала різні форми GOTO, включаючи знамениті присвоєні Фортранту (в) та арифметичні готи, якщо я правильно згадую.
njuffa

@njuffa "Як фахівець з оптимізації програмного забезпечення я погоджуюся, що неструктурований потік управління може кидати компілятори (і люди!) для циклу." - ще деталі? Я подумав, що практично кожен оптимізуючий компілятор використовує SSA як ІР, що означає, що він використовує гото-подібний код під ним.
Maciej Piechotka

@MaciejPiechotka Я не інженер-компілятор. Так, сучасні компілятори, схоже, використовують SSA у своєму проміжному представництві. Компілятори віддають перевагу конструкціям керування з одним входом та одним виходом, не знаєте, як використання SSA в цьому грає? Спостереження за генерованим машинним кодом та використанням ресурсів компілятора та дискусіями з інженерами-компіляторами неструктурований потік управління заважає оптимізувати перетворення коду, імовірно, через проблему "вихід". Використання ресурсів (час, пам'ять) може мати негативний вплив на продуктивність коду, якщо компілятор вирішить пропустити оптимізацію як занадто дорогу.
njuffa

12

return, break, continueІ throw/ catchвсе по суті GOTOS - вони все передачі управління в іншій частині коду і все вони можуть бути реалізовані з допомогою GOTOS - насправді я зробив це один раз в шкільному проекті, Паскаля інструктор казав , наскільки краще Паскаль , ніж основні через структуру ... тому мені довелося суперечити ...

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

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

Порівняно з аналогічними твердженнями щодо управління потоком, GOTO можна зробити так само легко, як слід (в одному випадку, що використовується у випадку, як ви запропонували), і кошмаром при зловживанні - і їх дуже легко зловживати ...

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

Багато інших структур було розроблено просто для того, щоб зробити ваш код більш зрозумілим: функції, об'єкти, обсяг, інкапсуляція, коментарі (!) ... а також більш важливі шаблони / процеси, такі як "DRY" (запобігання дублювання) та "YAGNI" (Зменшення надмірного узагальнення / ускладнення коду) - все насправді імпортує лише для НАЙКЛЮЧЕНОГО хлопця, щоб прочитати ваш код (Хто, ймовірно, ви будете - після того, як ви забули більшість того, що ви робили в першу чергу!)


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

« , І / все по суті GOTOS» Чи не згоден, колишнє повагу Догмати структурованого програмування (хоча можна стверджувати про винятки), йти до безумовно не робить. Зважаючи на це питання, цим зауваженням не дуже багато приділяється. returnbreakcontinuethrowcatch
Ерік

@eric Ви можете змоделювати будь-яку заяву з GOTOs. Ви можете переконатися, що всі GOTO погоджуються зі структурованими принципами програмування - вони просто мають інший синтаксис і повинні, щоб точно дублювати функціональність, включати інші операції, такі як "якщо". Перевага структурованих версій полягає в тому, що вони обмежуються лише підтримкою певних цілей - ви ЗНАЄте, коли побачите продовження, де приблизно буде розміщена ціль. Причину, про яку я згадував, полягала в тому, що проблема полягає в жорстокості, а не в тому, що її не можна правильно використовувати.
Білл К

7

GOTOє інструментом. Його можна використовувати для добра або для зла.

У погані старі часи, з FORTRAN та BASIC, це був чи не єдиний інструмент.

Дивлячись на код тих часів, коли ти бачиш, GOTOти повинен з'ясувати, чому він є. Це може бути частиною стандартної ідіоми, яку ви можете швидко зрозуміти ... або може бути частиною якоїсь контрольної структури кошмарів, якої ніколи не було. Ви не знаєте, поки не подивилися, і легко помилитися.

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

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

Швидкий перехід до сьогодні. Ви викладач програмування. Ви можете сказати: "У більшості випадків слід використовувати нові вдосконалені конструкції, але в деяких випадках простий GOTOможе бути більш читабельним". Студенти цього не розуміють. Вони збираються зловживати, GOTOщоб зробити нечитабельний код.

Натомість ви говорите " GOTOпогано. GOTOЗло. Невдалий GOTOіспит". Студенти будуть розуміти , що !


4
Це насправді справедливо для всіх застарілих речей. Глобали. Одно буквені назви змінних. Самостійний модифікаційний код. Евал. Навіть, підозрюю, нефільтроване введення користувачів. Після того, як ми умовили себе уникати таких речей, як чума, тоді ми знаходимось у підходящому становищі, щоб оцінити, чи певне їх використання, добре поставлене за ознакою, може бути правильним рішенням конкретної проблеми. До цього ми найкраще ставитися до них як до просто заборонених.
Деві Морган

4

За винятком gotoвсіх конструкцій потоку в PHP (і більшості мов), ієрархічно розміщуються.

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

a;
foo {
    b;
}
c;

Незалежно від того, що управління конструкцією fooє ( if, whileі т.д.), є тільки певні дозволені замовлення a, bі c.

Ви могли мати a- b- c, або a- cабо навіть a- b- b- b- c. Але ви ніколи не могли мати b- cабо a- b- a- c.

... якщо у вас немає goto.

$a = 1;
first:
echo 'a';
if ($a === 1) {
    echo 'b';
    $a = 2;
    goto first;
}
echo 'c'; 

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

gotos мають місце, але в основному як мікрооптимізація на мовах низького рівня. IMO, в PHP немає хорошого місця для цього.


FYI, приклад коду можна написати навіть краще, ніж будь-які ваші пропозиції.

if(!in_array($ip, $ips, true)) {
    throw new Exception('Not allowed');
}

2

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

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

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

Більшість сучасних мов мають структури управління, які роблять GOTO непотрібним. У таких, як Java, її навіть немає.

Насправді, термін код spaguetti походить від суперечливих , важко слідуючих причин коду неструктурованими структурами розгалуження.


6
gotoможе зробити код легким для читання. Коли ви створили зайві змінні та вкладені гілки порівняно з одним стрибком, код набагато складніше читати та розуміти.
Матвій Віт

@MatthewWhited Можливо, якщо у вас є одне гото за методом десяти рядків. Але більшість методів не є десятьма рядками, і в більшості випадків, коли люди використовують GOTO, вони не використовують його "лише цей раз".
Тулен Кордова

2
@MatthewWhited Насправді термін spaguetti код походить від перекрученого , важко слідуючого коду , викликаного неструктурованими гіллястими структурами. Або код спагетті тепер простіше червоного кольору? Можливо. Вініл повертається, чому б не GOTO.
Тулен Кордова

3
@Tulains Я маю вірити, що такі погані речі існують, тому що люди продовжують скаржитися на це, але більшість випадків, коли я бачу goto, що це - не приклади змішаного коду спагетті, а натомість досить прості речі, часто імітують схеми управління потоком на мовах, які не мають «т мати синтаксис для цього: два найбільш поширених прикладів , щоб вирватися з декількох циклів і , наприклад , в ОП , де gotoвикористовуються для реалізації for- else.

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

1

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

Крім того, що сказав JacquesB (обробка помилок в C), ви використовуєте gotoдля виходу з вкладеного циклу, що ви можете зробити, використовуючи break. У цьому випадку вам краще скористатися break.

Але якщо у вас був вкладений сценарій циклу, то використання gotoбуло б більш елегантним / простішим. Наприклад:

$allowed = false;

foreach ($ips as $i) {
    foreach ($ips2 as $i2) {
        if ($ip === $i && $ip === $i2) {
            $allowed = true;
            goto out;
        }
    }
}

out:

if (!$allowed) {
    throw new Exception('Not allowed');
}

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

Бонусний бал: якщо ваш список IP-адрес невеликий, ваш метод прекрасний. Але якщо список зростає, знайте, що ваш підхід має найгіршу асимптотичну складність виконання O (n) . У міру того, як ваш список зростає, ви можете скористатися іншим методом, який досягає O (log n) (наприклад, структури дерева) або O (1) (хеш-таблиця без зіткнень).


6
Я не впевнений у PHP, але багато мов підтримуватимуть використання breakта continueкількість (для розбиття / продовження багатьох шарів циклів) або мітки (для розриву / продовження циклу з цією міткою), яка з них, як правило, повинна бути бажано використовувати gotoдля вкладених петель.
8bittree

@ 8bittree хороший момент. Я не знав, що перерва PHP - це фантазія. Я знаю лише, що перерва С не така фантазія. Перерва Перла (вони називають його останньою ) також раніше був схожий на C (тобто не фантазійний як PHP), але він -то- став фантазійним через деякий момент. Я думаю, моя відповідь стає все менш корисною, оскільки все більше мов представляють модні версії перерви :)
пещерний працівник

3
перерва зі значенням глибини не вирішить проблему без додаткової змінної. Змінна за своєю сутністю, яка створює додатковий рівень складності.
Метью Віт

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

@ NPSF3000 Чи можете ви запропонувати приклад вкладеного циклу, з якого ви можете вийти, не використовуючи оператор goto , а також використовувати мову, яка не має фантазійної версії перерви, яка визначає глибину?
печерний людина

0

За допомогою goto я можу писати швидший код!

Правда. Не байдуже.

Йдемо в зборах! Вони просто називають це jmp.

Правда. Не байдуже.

Гото вирішує проблеми простіше.

Правда. Не байдуже.

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

Правда. Однак я був таким дисциплінованим кодером. Я бачив, що з часом відбувається з кодом. Gotoпочинається добре. Потім виникає бажання повторно використовувати код. Досить скоро я опиняюсь на точці перерви, не маючи проклятого поняття, що відбувається навіть після перегляду стану програми. Gotoускладнює міркування про код. Ми працювали дуже важко Створення while, do while, for, for each switch, subroutines, functions, і більше за все тому , що робить цей матеріал з ifі gotoважко на мозок.

Так ні. Ми не хочемо дивитися на це goto. Впевнений, що він живий і здоровий у двійковому, але нам це не потрібно бачити в джерелі. Насправді, ifпочинає виглядати трохи хитко.


1
"Гото вирішує проблеми просто". / "Правда. Байдуже". - Мені б не хотілося бачити ваш код, коли ви навмисно уникаєте простих рішень на користь того, що є найбільш розширеним. (Чув про YAGNI?)
користувач253751

1
@Wildcard if і goto - це дуже прості способи вирішення проблем, які найкраще вирішуються іншими способами. Вони низько висячі плоди. Мова не про конкретну мову. Gotoдозволяє абстрагувати проблему, зробивши з неї якусь іншу проблему бітів. Ifдозволяє вибрати цю абстракцію. Є кращі способи абстрагування та кращі способи вибору абстракції. Поліморфізм для одного.
candied_orange

2
Хоча я з вами згоден, це відповідь погано сформульована. "Правда, байдуже" не є переконливим аргументом ні для чого. Я думаю, що ваше головне повідомлення таке: хоча goto приваблює людей, які віддають перевагу використанню ефективних, потужних інструментів, це призводить до напрочуд величезної кількості витраченого часу пізніше, навіть якщо дотримуватися обережності.
Артелій

1
@artelius Тема "справді, не байдуже" не має бути переконливою. Це покликане проілюструвати багато пунктів, які я визнаю, і все ще зіткнуся з цим. Таким чином, сперечатися зі мною ці моменти безглуздо. Оскільки це не моя суть. Отримайте крапку?
candied_orange

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

-1

Мови складання, як правило, мають лише умовні / безумовні стрибки (еквівалент GOTO. Старіші реалізації FORTRAN та BASIC не мали операторів керування блоком, що перевищують підрахунок ітерації (цикл DO), залишаючи весь інший потік управління IF та GOTOs. Цикл DO у ці мови були закінчені числовим позначенням. В результаті код, написаний для цих мов, міг бути, і часто був важким для дотримання та схильним до помилок.

Щоб підкреслити суть, є вигадливо вигаданий вислів " ПРИЙДІТЬ ВІД ".

Практично не потрібно використовувати GOTO в таких мовах, як C, C ++, C #, PASCAL, Java тощо; можуть бути використані альтернативні конструкції, які майже напевно будуть настільки ж ефективними та набагато більш досяжними. Це правда, що один GOTO у вихідному файлі не буде проблемою. Проблема полягає в тому, що не потрібно багато, щоб зробити одиницю коду важкою для дотримання та схильною до помилок у підтримці. Ось чому загальноприйнята мудрість - уникати GOTO, коли це можливо.

Ця стаття з вікіпедії в заяві goto може бути корисною

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