Используя Возврат Стильно - PullRequest
2 голосов
/ 20 февраля 2011

Допустим, у меня было много кода между оператором if. Правильнее ли сделать быструю проверку if-else перед этим, а в случае неудачи вернуть.

ИЛИ создать оператор if с большим количеством промежуточного кода, но не использовать return?

ИЛИ это просто вопрос предпочтений?

так что мои 2 варианта: если что-то){ вернуть } еще // здесь много кода

если (что-то) { // здесь много кода }

Ответы [ 4 ]

3 голосов
/ 20 февраля 2011

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

Редактировать, чтобы добавить: В том же духе, вы всегда должны проверять случаи, которые с наибольшей вероятностью будут нарушены в первую очередь, это разумный совет при структурированииа также ваши условия (|| и && проверки)

2 голосов
/ 20 февраля 2011

Я думаю, что это выглядит намного лучше:

func() {
   if(someCondition) {
      return;
   }

   if(otherCondition) {
      return;
   }

   //lots of code
}

, чем это:

func() {
   if(someCondition) {
      return;
   } else if(otherCondition) {
      return;
   } else {
      //lots of code
   }
}

или вот это:

func() {
   if(!someCondition) {
      if(!otherCondition) {
         //lots of code
      }
   }
}

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

0 голосов
/ 20 февраля 2011

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

Чтобы улучшить читабельность, я стремлюсь следовать следующим правилам.

Правило 1 . Сохраняйте return как последнюю строку кода , что бы ни находилось посередине.Другими словами, не разбрасывайте операторы return, когда захотите, просто потому, что вы не уверены, что ваша структура if-else будет каскадно перед самым последним возвратом.

За исключением простых методов, я предпочитаю структуру типа

MyType func() {
    MyType result ;
    if ( condition ) {
        result = result_1 ;
    } else {
        result = result_2 ;
    }
    return result ;
}

по сравнению с предположительно более простой

MyType func() {
    if ( condition ) {
        return result_1 ;
    } else {
        return result_2 ;
    }
}

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

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

Многие новички вмоя команда начала кодировать подобные вещи

MyType func (ArgType arg1,...) {
    if ( arg1 == null ) {
        throw new Exception ( "hey dummy, we don't take null arg1) ;
        // or return null ;
        }
    if ( arg2 == null ) {
        // you got the picture...
        }
    // wow at last !!! all checks done
    // Combine args and return result...
}

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

Я предпочитаю

MyType func (ArgType arg1,...) {
    MyType result ;
    if ( try_to_compact_all_checks_here ) {
        // Combine args and return result...
    } else {
        // throw, log, nullify result etc
    }
    return result ;
}

Если условие «try_to_compact_all_checks_here» не помещается в одну строку, я даже иногда предпочитаю убираться с дороги и инкапсулирую все проверки в частную функцию.Даже если он вызывается только один раз.

Правило 3 . Сохраняйте количество строк в операторе if / else на разумном уровне (обычно оно должно умещаться на одном экране в вашей IDE) .Для этого иногда можно извлечь некоторую логику и вставить ее в частную функцию.Совершенно никаких проблем.Все современные IDE делают это для вас в 2 клика.

Таким образом, в основном предыдущий шаблон становится.

MyType func (ArgType arg1,...) {
    MyType result ;
    if ( checks_here ) {
        // 1 to 20 lines max, 
        encapsulate lengthy logic in full fledged private methods.
    } else {
        // throw, log, nullify result etc
    }
    return result ;
}

Правило 4 . Внутренние IF всегда должны иметь ELSE, и этот ELSE должен отличаться от внешнего ELSE .

Объяснение: Если я получу

MyType func (ArgType arg1,...) {
    MyType result ;
    if ( check_1 ) {
        if (check_2) {
           Do the real work
        } else {
           treat error condition
        }
    } else {
        same error condition as above
    }
    return result ;
}

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

MyType func (ArgType arg1,...) {
    MyType result ;
    if ( check_1 && check_2) {
        Do the real work
    } else {
        same error condition as above
    }
    return result ;
}

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

0 голосов
/ 20 февраля 2011

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

Однако, если в коде так много if-else, вы можете переосмыслить свой дизайн . Refactory может быть лучшим выбором.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...