Должна ли функция иметь только один оператор возврата?

Есть ли веские причины, по которым лучше использовать только один оператор возврата в функции?

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

781
задан David 31 авг. '08 в 12:26
источник поделиться

50 ответов

  • 1
  • 2

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

public void DoStuff(Foo foo)
{
    if (foo != null)
    {
        ...
    }
}

... можно сделать более читаемым (IMHO) следующим образом:

public void DoStuff(Foo foo)
{
    if (foo == null) return;

    ...
}

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

743
ответ дан Matt Hamilton 31 авг. '08 в 12:31
источник поделиться

Никто не упомянул или не процитировал Code Complete, поэтому я сделаю это.

17.1 return

Минимизировать количество возвратов в каждой рутине. Труднее понять рутину, если, читая ее внизу, вы не знаете, что она вернулась где-то выше.

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

355
ответ дан Chris S 09 апр. '09 в 14:47
источник поделиться

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

string fooBar(string s, int? i) {
  string ret = "";
  if(!string.IsNullOrEmpty(s) && i != null) {
    var res = someFunction(s, i);

    bool passed = true;
    foreach(var r in res) {
      if(!r.Passed) {
        passed = false;
        break;
      }
    }

    if(passed) {
      // Rest of code...
    }
  }

  return ret;
}

Сравните это с кодом, в котором разрешено несколько точек выхода: -

string fooBar(string s, int? i) {
  var ret = "";
  if(string.IsNullOrEmpty(s) || i == null) return null;

  var res = someFunction(s, i);

  foreach(var r in res) {
      if(!r.Passed) return null;
  }

  // Rest of code...

  return ret;
}

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

229
ответ дан ljs 31 авг. '08 в 12:46
источник поделиться

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

С теорией "единственной точки выхода" вы неизбежно завершаете код, который выглядит так:

function()
{
    HRESULT error = S_OK;

    if(SUCCEEDED(Operation1()))
    {
        if(SUCCEEDED(Operation2()))
        {
            if(SUCCEEDED(Operation3()))
            {
                if(SUCCEEDED(Operation4()))
                {
                }
                else
                {
                    error = OPERATION4FAILED;
                }
            }
            else
            {
                error = OPERATION3FAILED;
            }
        }
        else
        {
            error = OPERATION2FAILED;
        }
    }
    else
    {
        error = OPERATION1FAILED;
    }

    return error;
}

Это не только делает код очень трудным для выполнения, но теперь скажите позже, что вам нужно вернуться назад и добавить операцию между 1 и 2. Вам нужно отступать от всей функции freaking и удачи убедитесь, что все ваши условия if/else и фигурные скобки подобраны правильно.

Этот метод делает работу с кодом чрезвычайно сложной и подверженной ошибкам.

191
ответ дан 17 of 26 31 авг. '08 в 15:50
источник поделиться

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

72
ответ дан Chris de Vries 31 авг. '08 в 12:38
источник поделиться

Как замечает Кент Бек при обсуждении оговорок охраны в Шаблоны реализации, при создании подпрограммы есть одна точка входа и выхода...

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

Я нахожу функцию, написанную с предложениями охраны намного проще, чем одна длинная вложенная группа операторов if then else.

62
ответ дан blank 31 авг. '08 в 12:48
источник поделиться

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

Другими словами, когда это возможно, пользу этого стиля

return a > 0 ?
  positively(a):
  negatively(a);

над этим

if (a > 0)
  return positively(a);
else
  return negatively(a);

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

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

61
ответ дан Apocalisp 07 сент. '08 в 21:06
источник поделиться

Я видел это в стандартах кодирования для С++, которые были зависанием от C, как если бы у вас не было RAII или другого автоматического управления памятью, тогда вам нужно очистить для каждого возврата, что либо означает, и-вставить очистку или goto (логически то же, что и "наконец" на управляемых языках), обе из которых считаются плохими. Если ваша практика заключается в использовании интеллектуальных указателей и коллекций на С++ или другой автоматической системе памяти, то для этого нет веских оснований, и это становится все о читаемости и многом другом.

43
ответ дан Pete Kirkham 31 авг. '08 в 12:48
источник поделиться

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

40
ответ дан Joel Coehoorn 20 марта '09 в 16:03
источник поделиться

Есть ли веские причины, почему лучше использовать только один оператор возврата в функции?

Да:

  • Единственная точка выхода дает отличное место для утверждения ваших пост-условий.
  • Быть способным разместить точку останова отладчика на одном возврате в конце функции часто полезно.
  • Меньшее количество возвратов означает меньшую сложность. Линейный код обычно проще понять.
  • Если попытка упростить функцию к одному возврату вызывает сложность, то это побуждает рефакторировать к более мелким, более общим, более понятным функциям.
  • Если вы находитесь на языке без деструкторов или если вы не используете RAII, то один возврат уменьшает количество мест, которые вы должны очистить.
  • Для некоторых языков требуется одна точка выхода (например, Pascal и Eiffel).

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

Обновить: По-видимому, рекомендации MISRA также поддерживают один выход.

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

38
ответ дан Adrian McCarthy 15 мая '09 в 1:04
источник поделиться

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

33
ответ дан Mark 23 июля '10 в 20:29
источник поделиться

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

19
ответ дан Scott Dorman 31 авг. '08 в 13:29
источник поделиться

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

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

14
ответ дан Ben Lings 14 июля '10 в 22:20
источник поделиться

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

public void DoStuff(Foo foo)
{
    if (foo == null) return;
}

Увидев этот код, я сразу же спрошу:

  • Является ли "foo" когда-либо нулевым?
  • Если да, то сколько клиентов "DoStuff" когда-либо называют функцию с нулевым "foo" ?

В зависимости от ответов на эти вопросы может быть, что

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

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

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

Объект, не содержащий POD С++ в области действия при выходе из функции, будет иметь вызванный деструктор. Там, где есть несколько операторов возврата, может быть, что в области есть разные объекты, поэтому список деструкторов для вызова будет другим. Поэтому компилятору необходимо сгенерировать код для каждого оператора return:

void foo (int i, int j) {
  A a;
  if (i > 0) {
     B b;
     return ;   // Call dtor for 'b' followed by 'a'
  }
  if (i == j) {
     C c;
     B b;
     return ;   // Call dtor for 'b', 'c' and then 'a'
  }
  return 'a'    // Call dtor for 'a'
}

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

Другая проблема связана с "Оптимизацией именного номинального значения" (также называемой "Копирование Elision", ISO С++ '03 12.8/15). С++ позволяет реализации пропускать вызов конструктора копирования, если он может:

A foo () {
  A a1;
  // do something
  return a1;
}

void bar () {
  A a2 ( foo() );
}

Просто принимая код как есть, объект 'a1' построен в 'foo', а затем его конструкцию копирования вызывается для построения 'a2'. Тем не менее, копирование elision позволяет компилятору построить 'a1' в том же месте в стеке как 'a2'. Поэтому нет необходимости "копировать" объект, когда функция возвращается.

Несколько точек выхода усложняют работу компилятора при попытке обнаружить это, и, по крайней мере, для относительно новой версии VС++ оптимизация не состоялась, когда тело функции имело несколько возвратов. Подробнее см. Именованная оптимизация возвращаемого значения в Visual С++ 2005.

14
ответ дан Richard Corden 17 сент. '08 в 21:01
источник поделиться

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

11
ответ дан John Channing 03 сент. '08 в 0:17
источник поделиться

Я заставляю себя использовать только один оператор return, поскольку он в некотором смысле генерирует запах кода. Позвольте мне объяснить:

function isCorrect($param1, $param2, $param3) {
    $toret = false;
    if ($param1 != $param2) {
        if ($param1 == ($param3 * 2)) {
            if ($param2 == ($param3 / 3)) {
                $toret = true;
            } else {
                $error = 'Error 3';
            }
        } else {
            $error = 'Error 2';
        }
    } else {
        $error = 'Error 1';
    }
    return $toret;
}

(Условия являются условными...)

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

  • Несколько возвратов
  • Рефакторинг в отдельные функции

Несколько возвратов

function isCorrect($param1, $param2, $param3) {
    if ($param1 == $param2)       { $error = 'Error 1'; return false; }
    if ($param1 != ($param3 * 2)) { $error = 'Error 2'; return false; }
    if ($param2 != ($param3 / 3)) { $error = 'Error 3'; return false; }
    return true;
}

Отдельные функции

function isEqual($param1, $param2) {
    return $param1 == $param2;
}

function isDouble($param1, $param2) {
    return $param1 == ($param2 * 2);
}

function isThird($param1, $param2) {
    return $param1 == ($param2 / 3);
}

function isCorrect($param1, $param2, $param3) {
    return !isEqual($param1, $param2)
        && isDouble($param1, $param3)
        && isThird($param2, $param3);
}

Конечно, это длиннее и немного грязно, но в процессе рефакторинга функции таким образом мы

  • создано несколько функций многократного использования,
  • сделал функцию более понятной для человека и
  • фокус функций зависит от того, почему значения верны.
11
ответ дан Jrgns 14 авг. '09 в 12:40
источник поделиться

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

Я лично никогда не слышал/не видел "лучших практик", утверждая, что у вас должно быть только одно выражение return.

По большей части, я стараюсь как можно скорее выйти из функции на основе логического пути (замечательные примеры - замечательные примеры).

10
ответ дан Rob Cooper 31 авг. '08 в 12:30
источник поделиться

Я считаю, что несколько возвратов обычно хороши (в коде, который я пишу на С#). Стиль с одним возвратом является задержкой с C. Но вы, вероятно, не кодируете в C.

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

Более чем один стиль возврата может быть плохой привычкой в ​​коде C, где ресурсы должны быть явно выделены, но такие языки, как Java, С#, Python или JavaScript, которые имеют такие конструкции, как автоматическая сборка мусора и try..finally блоков (и using блоков в С#), и этот аргумент не применяется - на этих языках очень редко требуется централизованное освобождение ресурсов вручную.

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

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

Я говорил о это более подробно в моем блоге.

10
ответ дан Anthony 27 июня '10 в 20:32
источник поделиться

Есть хорошие вещи, чтобы сказать о наличии единственного пункта выхода, так же как есть плохие вещи, чтобы сказать о неизбежном "arrow" , которое дает результаты.

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

Оба спартанское программирование в статье "SSDSLPedia" и точка выхода одной функции в статье "Репозиторий хранилища репозитория в Портленде" содержат некоторые проницательные аргументы. Кроме того, конечно, этот пост следует рассмотреть.

Если вам действительно нужна единая точка выхода (например, на любом языке, не поддерживающем исключения), чтобы освободить ресурсы в одном месте, я считаю, что тщательное приложение goto должно быть хорошим; см., например, этот довольно надуманный пример (сжатый для сохранения экранной недвижимости):

int f(int y) {
    int value = -1;
    void *data = NULL;

    if (y < 0)
        goto clean;

    if ((data = malloc(123)) == NULL)
        goto clean;

    /* More code */

    value = 1;
clean:
   free(data);
   return value;
}

Лично я вообще не люблю программирование стрелок больше, чем мне не нравятся многочисленные точки выхода, хотя оба они полезны при правильном применении. Разумеется, лучше всего структурировать вашу программу, чтобы не требовать ни того, ни другого. Нарушение функции в несколько кусков обычно помогает:)

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

int g(int y) {
  value = 0;

  if ((value = g0(y, value)) == -1)
    return -1;

  if ((value = g1(y, value)) == -1)
    return -1;

  return g2(y, value);
}

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

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

Короче говоря,

  • Немногие возвраты лучше, чем многие возвраты
  • Более одного возврата лучше, чем огромные стрелки, и сторожевые предложения, как правило, в порядке.
  • Исключения могут/должны, вероятно, заменять большинство "защитных оговорок", если это возможно.
10
ответ дан Henrik Gustafsson 31 авг. '08 в 17:13
источник поделиться

Вы знаете, что поговорка - <сильная > красота находится в глазах смотрящего.

Некоторые люди клянутся NetBeans, а некоторые - IntelliJ IDEA, некоторые из Python, а некоторые - PHP.

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

public void hello()
{
   if (....)
   {
      ....
   }
}

Вопрос о видимости и ремонтопригодности.

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

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

Помню, 20 лет назад мой коллега был уволен за то, что сегодня можно было бы назвать стратегией гибкой разработки. У него был тщательный поэтапный план. Но его менеджер кричал на него:" Вы не можете постепенно добавлять функции пользователям! Вы должны придерживаться waterfall. "Его реакция на менеджера заключалась в том, что постепенное развитие было бы более точным для потребностей клиентов. Он верил в развитие потребностей клиентов, но менеджер верил в кодирование" требований клиентов".

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

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

качество = точность, ремонтопригодность и прибыльность.

Все остальные правила исчезают в фоновом режиме. И, конечно же, это правило никогда не исчезает:

Лень - это добродетель хорошего программист.

9
ответ дан Blessed Geek 15 июля '10 в 8:27
источник поделиться

Я наклоняюсь к предложениям охраны, чтобы вернуться раньше и иначе выйти в конце метода. Единое правило входа и выхода имеет историческое значение и особенно полезно при работе с устаревшим кодом, который работает до 10 страниц формата А4 для одного метода C++ с несколькими возвращаемыми значениями (и многими дефектами). Совсем недавно принятая хорошая практика заключается в том, чтобы держать методы малыми, что делает несколько выходов менее полным для понимания. В следующем примере Kronoz, скопированном сверху, возникает вопрос, что происходит в //Rest code...?:

void string fooBar(string s, int? i) {

  if(string.IsNullOrEmpty(s) || i == null) return null;

  var res = someFunction(s, i);

  foreach(var r in res) {
      if(!r.Passed) return null;
  }

  // Rest of code...

  return ret;
}

Я понимаю, что пример несколько надуман, но у меня возникнет соблазн реорганизовать цикл foreach в оператор LINQ, который затем можно было бы рассматривать как предложение охраны. Опять же, в надуманном примере намерение кода не является очевидным, а someFunction() может иметь какой-то другой побочный эффект, или результат может быть использован в//остатке кода....

if (string.IsNullOrEmpty(s) || i == null) return null;
if (someFunction(s, i).Any(r => !r.Passed)) return null;

Предоставление следующей реорганизованной функции:

void string fooBar(string s, int? i) {

  if (string.IsNullOrEmpty(s) || i == null) return null;
  if (someFunction(s, i).Any(r => !r.Passed)) return null;

  // Rest of code...

  return ret;
}
9
ответ дан David Clarke 17 февр. '11 в 23:42
источник поделиться

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

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

7
ответ дан Jon Limjap 31 авг. '08 в 16:38
источник поделиться

Одна хорошая причина, по которой я могу думать, - это поддерживать код: у вас есть одна точка выхода. Если вы хотите изменить формат результата,... это намного проще реализовать. Кроме того, для отладки вы можете просто придерживаться точки останова:)

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

7
ответ дан OysterD 31 авг. '08 в 12:31
источник поделиться

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

6
ответ дан Phil Bennett 31 авг. '08 в 12:39
источник поделиться

Единая точка выхода - все остальное равно - делает код более читаемым. Но есть улов: популярное строительство

resulttype res;
if if if...
return res;

является подделкой, "res =" не намного лучше, чем "return". Он имеет один оператор return, но несколько точек, где функция фактически заканчивается.

Если у вас есть функция с несколькими возвращаемыми значениями (или "res =" ), часто бывает хорошей идеей разбить ее на несколько меньших функций с одной точкой выхода.

6
ответ дан ima 11 сент. '08 в 10:39
источник поделиться

Моя обычная политика заключается в том, чтобы иметь только один оператор возврата в конце функции, если только сложность кода не будет значительно уменьшена путем добавления большего количества. На самом деле, я скорее поклонник Eiffel, который применяет единственное правило возврата, не имея оператора возврата (там есть только переменная "результат" с автоматическим созданием, чтобы привести ваш результат).

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

6
ответ дан Matt Sheppard 11 сент. '08 в 10:48
источник поделиться

Я голосую за Одиночное возвращение в конце в качестве ориентира. Это помогает очистить общий код очистки... Например, посмотрите на следующий код...

void ProcessMyFile (char *szFileName)
{
   FILE *fp = NULL;
   char *pbyBuffer = NULL:

   do {

      fp = fopen (szFileName, "r");

      if (NULL == fp) {

         break;
      }

      pbyBuffer = malloc (__SOME__SIZE___);

      if (NULL == pbyBuffer) {

         break;
      }

      /*** Do some processing with file ***/

   } while (0);

   if (pbyBuffer) {

      free (pbyBuffer);
   }

   if (fp) {

      fclose (fp);
   }
}
5
ответ дан Alphaneo 27 апр. '09 в 9:07
источник поделиться

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

Perl 6: Плохой пример

sub Int_to_String( Int i ){
  given( i ){
    when 0 { return "zero" }
    when 1 { return "one" }
    when 2 { return "two" }
    when 3 { return "three" }
    when 4 { return "four" }
    ...
    default { return undef }
  }
}

лучше писать так:

Perl 6: Хороший пример

@Int_to_String = qw{
  zero
  one
  two
  three
  four
  ...
}
sub Int_to_String( Int i ){
  return undef if i < 0;
  return undef unless i < @Int_to_String.length;
  return @Int_to_String[i]
}

Обратите внимание, что это был просто быстрый пример

5
ответ дан Brad Gilbert 15 сент. '08 в 18:53
источник поделиться

Если хорошо записать только мнение, то мое:

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

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

Функция (если она действительно представляет собой функцию/запрос в соответствии с разделом Query-Command), например, см. например, Eiffel programming lang), просто ДОЛЖНО определить столько точек возврата, сколько сценариев потока управления. Это гораздо более ясное и математически последовательное; и это способ записи функций (т.е. запросов)

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

4
ответ дан Bubba88 08 мая '10 в 8:29
источник поделиться

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

Но нет, нет ничего плохого в одном/много возвращаемых операторов. На некоторых языках это более совершенная практика (С++), чем в других (C).

4
ответ дан hazzen 07 сент. '08 в 21:19
источник поделиться
  • 1
  • 2

Другие вопросы по меткам