Инвертирование, “если” оператор для сокращения вложения

255
задан Peter Mortensen 30 June 2014 в 06:19
поделиться

15 ответов

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

double getPayAmount() {
    double result;
    if (_isDead) result = deadAmount();
    else {
        if (_isSeparated) result = separatedAmount();
        else {
            if (_isRetired) result = retiredAmount();
            else result = normalPayAmount();
        };
    }
     return result;
};

В этом случае, если _isDead верно, мы можем сразу выйти из метода. Могло бы быть лучше структурировать его этот путь вместо этого:

double getPayAmount() {
    if (_isDead)      return deadAmount();
    if (_isSeparated) return separatedAmount();
    if (_isRetired)   return retiredAmount();

    return normalPayAmount();
};   

я выбрал этот код от каталог рефакторинга. Этот определенный рефакторинг называют: Замените Вложенное Условное выражение Пунктами охраны.

281
ответ дан Joshua Pinter 23 November 2019 в 02:44
поделиться

Существует несколько преимуществ для этого вида кодирования, но для меня большая победа, если можно возвратиться быстрый, можно улучшить скорость приложения. IE я знаю, что из-за Предварительного условия X, которое я могу возвратить быстро с ошибкой. Это избавляется от ошибочных случаев сначала и уменьшает сложность Вашего кода. В большом количестве случаев, потому что конвейер CPU может быть теперь быть более чистым, он может остановить конвейерные катастрофические отказы или переключатели. Во-вторых, если Вы находитесь в цикле, повреждение или возвращение быстро могут сохранить Вас много CPU. Некоторые программисты используют инварианты цикла, чтобы сделать этот вид быстрого выхода, но в этом Вы можете, повредил Ваш конвейер CPU, и даже создайте память, ищут проблему и означают, CPU должен загрузиться от внешнего кэша. Но в основном я думаю, что необходимо сделать то, что Вы предназначили, это - конец, цикл или функция не создают путь сложного кода только для реализации некоторого абстрактного понятия корректного кода. Если единственный инструмент, который Вы имеете, является молотком тогда, все похоже на гвоздь.

0
ответ дан David Allan Finch 23 November 2019 в 02:44
поделиться

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

    function do_something( data ){

      if (!is_valid_data( data )) 
            return false;


       do_something_that_take_an_hour( data );

       istance = new object_with_very_painful_constructor( data );

          if ( istance is not valid ) {
               error_message( );
                return ;

          }
       connect_to_database ( );
       get_some_other_data( );
       return;
    }

, Возможно, первый "возврат" это не НАСТОЛЬКО интуитивно, но это действительно сохраняет. Существует слишком много "идей" о чистых кодах, этому просто нужно больше практики для потери их "субъективных" плохих идей.

0
ответ дан Joshi Spawnbrood 23 November 2019 в 02:44
поделиться

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

0
ответ дан Bluenuance 23 November 2019 в 02:44
поделиться

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

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

2
ответ дан JohnIdol 23 November 2019 в 02:44
поделиться

Это - дело вкуса.

Мой нормальный подход должен был бы избежать одной строки IFS и возвраты посреди метода.

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

2
ответ дан Colin Pickard 23 November 2019 в 02:44
поделиться

Это просто спорно. Нет никакого "соглашения среди программистов" по вопросу о раннем возврате. Это всегда субъективно, насколько я знаю.

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

я не думаю, что Вы получите окончательный ответ на этот вопрос.

4
ответ дан unwind 23 November 2019 в 02:44
поделиться

Много серьезных оснований [приблизительно 112], как код похож . Но что относительно результаты ?

Позволяют нам смотреть к некоторому коду C# и его IL скомпилированная форма:


using System;

public class Test {
    public static void Main(string[] args) {
        if (args.Length == 0) return;
        if ((args.Length+2)/3 == 5) return;
        Console.WriteLine("hey!!!");
    }
}

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

сгенерированный код IL делает следующее:

  1. , Если первое условие является ложью, переходами к коду, где второе.
  2. , Если это - истинные переходы к последней инструкции. (Отметьте: последняя инструкция является возвратом).
  3. Во втором условии то же происходит после того, как результат вычисляется. Сравните и: добрался до Консоли. WriteLine, если ложь или до конца если это верно.
  4. Печать сообщение и возврат.

, Таким образом, кажется, что код перейдет до конца. Что, если мы делаем нормальное если с вложенным кодом?

using System;

public class Test {
    public static void Main(string[] args) {
        if (args.Length != 0 && (args.Length+2)/3 != 5) 
        {
            Console.WriteLine("hey!!!");
        }
    }
}

результаты весьма схожи в инструкциях IL. Различие - то, что, прежде чем было к переходам на условие: если ложное движение к следующей части кода, если истинное движение, чтобы тогда закончиться. И теперь код IL течет лучше и имеет 3 перехода (компилятор оптимизировал это немного): 1. Первый переход: когда Длина 0 к части, где код переходит снова (Третий переход) до конца. 2. Во-вторых: посреди второго условия избежать одной инструкции. 3. В-третьих: если второе условие является ложью, перейдите до конца.

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

5
ответ дан graffic 23 November 2019 в 02:44
поделиться

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

, например,

 bool PerformDefaultOperation()
 {
      bool succeeded = false;

      DataStructure defaultParameters;
      if ((defaultParameters = this.GetApplicationDefaults()) != null)
      {
           succeeded = this.DoSomething(defaultParameters);
      }

      return succeeded;
 }

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

7
ответ дан ilitirit 23 November 2019 в 02:44
поделиться

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

9
ответ дан Jon Limjap 23 November 2019 в 02:44
поделиться

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

if (something) {
    // a lot of indented code
}

Вы инвертируете условие и повреждение, если то обратное условие выполняется

if (!something) return false; // or another value to show your other code the function did not execute

// all the code from before, save a lot of tabs

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

Вы будете видеть лучшие примеры того, где это может быть применено во вложенных условиях:

if (something) {
    do-something();
    if (something-else) {
        do-another-thing();
    } else {
        do-something-else();
    }
}

по сравнению с:

if (!something) return;
do-something();

if (!something-else) return do-something-else();
do-another-thing();

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

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

11
ответ дан Oli 23 November 2019 в 02:44
поделиться

Несколько точек возврата были проблемой в C (и к C++ меньшей степени), потому что они вынудили Вас копировать код очистки перед каждой из точек возврата. Со сборкой "мусора", try | finally конструкция и using блоки, нет действительно никакой причины, почему необходимо бояться их.

В конечном счете это сводится к тому, что Вы и Ваши коллеги находите легче читать.

14
ответ дан Richard Poole 23 November 2019 в 02:44
поделиться

Это, конечно, субъективно, но я думаю, что это сильно изменяет к лучшему две точки:

  • теперь сразу очевидно, что Ваша функция не имеет ничего больше, чтобы сделать, если condition содержит.
  • Это подавляет уровень вложенности. Вложение повреждает удобочитаемость больше, чем Вы думали бы.
18
ответ дан Deestan 23 November 2019 в 02:44
поделиться

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

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

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

50
ответ дан Scott Langham 23 November 2019 в 02:44
поделиться

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

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

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

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

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

Плохая удобочитаемость кода будет.

101
ответ дан Peter Mortensen 23 November 2019 в 02:44
поделиться
Другие вопросы по тегам:

Похожие вопросы: