Из книги « Полный код» приводится следующая цитата:
«Положите нормальный случай после,
if
а не послеelse
»
Это означает, что в else
случае должны быть указаны исключения / отклонения от стандартного пути .
Но Прагматичный Программист учит нас «рано падать» (стр. 120).
Какому правилу я должен следовать?
if
веток вернется, сначала используйте ее. И избегайтеelse
остальной части кода, вы уже вернулись, если предварительные условия не удалось. Код легче читать, меньше отступов ...Ответы:
«Сбой рано» не означает, какая строка кода появляется раньше в тексте. Он говорит вам об обнаружении ошибок на самом раннем этапе обработки , чтобы вы не могли случайно принять решения и вычисления на основе уже неисправного состояния.
В конструкции
if
/ выполняетсяelse
только один из блоков, поэтому нельзя сказать, что ни один из них составляет «более ранний» или «более поздний» этап. Как их заказать, поэтому вопрос читабельности, и «ранний сбой» не влияет на решение.источник
if/else
конструкциях это, вероятно, не имеет значения. Но те, которые вызываются в цикле или имеют много операторов в каждом блоке, могут работать быстрее с самым распространенным условием.Если ваше
else
утверждение содержит только код ошибки, то, скорее всего, его там не должно быть.Вместо этого:
сделай это
Вы не хотите глубоко вкладывать свой код просто для того, чтобы включить проверку ошибок.
И, как уже говорили все остальные, два совета не противоречат друг другу. Один о порядке выполнения , другой о порядке кода .
источник
if
и исключительный поток в блок послеelse
не применяются, если у вас нетelse
! Защитные операторы, подобные этой, являются предпочтительной формой для обработки ошибок в большинстве стилей кодирования.Вы должны следовать за ними обоими.
Совет «Ранний сбой» / ранний сбой означает, что вы должны как можно скорее проверить свои входные данные на возможные ошибки.
Например, если ваш метод принимает размер или число, которое должно быть положительным (> 0), то ранняя рекомендация при сбое означает, что вы проверяете это условие в самом начале вашего метода, а не ожидаете, пока алгоритм выдаст бессмыслицу. Результаты.
Совет о том, чтобы сначала поставить нормальный случай, означает, что если вы проверяете условие, то сначала должен быть наиболее вероятный путь. Это помогает в производительности (так как предсказание ветвления процессора будет правильнее чаще) и удобочитаемости, потому что вам не нужно пропускать блоки кода при попытке выяснить, что функция делает в обычном случае.
Этот совет на самом деле не применим, когда вы тестируете предварительное условие и сразу же спасаетесь (используя утверждения или
if (!precondition) throw
конструкции), потому что нет никакой обработки ошибок, чтобы пропустить ее при чтении кода.источник
if(cond){/*more likely code*/}else{/*less likely code*/}
работает быстрее, чемif(!cond){/*less likely code*/}else{/*more likely code*/}
из-за предсказания ветвлений. Я думаю, что предсказание ветвлений не является предвзятым ниif
дляelse
оператора, ни для оператора, а только учитывает историю. Так что, еслиelse
это произойдет с большей вероятностью, оно должно быть в состоянии предсказать это так же хорошо. Это предположение неверно?Я думаю, что @JackAidley уже сказал суть этого , но позвольте мне сформулировать это так:
без исключений (например, C)
В обычном потоке кода у вас есть:
В случае с ошибкой раньше, ваш код внезапно читает:
Если вы обнаружите этот шаблон -
return
вelse
(или дажеif
) блоке, немедленно переделайте его, чтобы у рассматриваемого кода не былоelse
блока:В реальном мире…
Это позволяет избежать слишком глубокого вложения и выполняет случай «вырваться раньше» (помогает сохранить ум - и поток кода - чистым) и не нарушает «положить более вероятную вещь в
if
часть», потому что просто нетelse
части ,C
и очисткаВдохновленный ответом на аналогичный вопрос (который получил это неправильно), вот как вы делаете очистку с C. Вы можете использовать одну или две точки выхода, вот одна для двух точек выхода:
Вы можете свернуть их в одну точку выхода, если нужно сделать меньше очистки:
Это использование
goto
прекрасно, если вы можете справиться с этим; Совет по отказу от использованияgoto
адресован людям, которые еще не могут самостоятельно решить, является ли использование хорошим, приемлемым, плохим, кодом спагетти или чем-то еще.Исключения
Вышесказанное говорит о языках без исключений, которые я предпочитаю сам (я могу использовать явную обработку ошибок гораздо лучше и с гораздо меньшим удивлением). Процитирую Игли:
Но вот предложение, как вы делаете это хорошо на языке с исключениями, и когда вы хотите использовать их хорошо:
возврат ошибки в случае исключений
Вы можете заменить большинство ранних
return
символов на исключение. Однако ваш обычный программный поток, т. Е. Любой поток кода, в котором программа не встретила, ну, исключение ... условие ошибки или что-то подобное, не должен вызывать никаких исключений.Это значит, что…
... хорошо, но ...
… не является. По сути, исключение не является элементом потока управления . Это также заставляет Операции выглядеть странно на вас («эти Java-программисты всегда говорят нам, что эти исключения являются нормальными») и может препятствовать отладке (например, сказать IDE, что нужно просто сломать любое исключение). Исключения часто требуют, чтобы среда выполнения разматывала стек для получения трассировок и т. Д. Вероятно, есть и другие причины против этого.
Это сводится к следующему: на языке, поддерживающем исключения, используйте все, что соответствует существующей логике и стилю и выглядит естественным. Если вы пишете что-то с нуля, договоритесь об этом заранее. Если вы пишете библиотеку с нуля, подумайте о ваших потребителях. (Никогда не используйте
abort()
в библиотеке также…) Но что бы вы ни делали, не, как правило, выдается исключение, если операция продолжается (более или менее) нормально после нее.общий совет относительно Исключения
Постарайтесь сначала использовать все исключения в программе, согласованные всей командой разработчиков. В основном, планируйте их. Не используйте их в изобилии. Иногда даже в C ++, Java ™, Python возврат ошибок лучше. Иногда это не так; используйте их с мыслью.
источник
goto fail;
скрытый в обличье.По моему мнению, «Условие охраны» - это один из лучших и самых простых способов сделать код читабельным. Я действительно ненавижу, когда вижу
if
в начале метода и не вижуelse
код, потому что это за кадром. Я должен прокрутить вниз, чтобы увидетьthrow new Exception
.Поместите проверки в начале, чтобы человеку, читающему код, не приходилось прыгать по всему методу, чтобы прочитать его, а вместо этого всегда сканировать его сверху вниз.
источник
(@mirabilos' ответ отлично, но вот как я думаю о вопросе , чтобы достичь такой же вывод :)
Я думаю о себе (или о ком-то еще), читающем код моей функции позже. Когда я читаю первую строку, я не могу делать никаких предположений относительно своего ввода (кроме тех, которые я не буду проверять в любом случае). Поэтому моя мысль такова: «Хорошо, я знаю, что собираюсь что-то делать со своими аргументами. Но сначала давайте« очистим их »- то есть убьем контрольные пути, по которым они мне не нравятся». Но в то же время Я не вижу нормальный случай как нечто обусловленное, я хочу подчеркнуть, что он нормальный.
источник
Этот вид упорядочения условий зависит от критичности рассматриваемого раздела кода и наличия возможных значений по умолчанию.
Другими словами:
A. критический раздел и нет значений по умолчанию => Fail Early
B. некритический раздел и значения по умолчанию => Использовать значения по умолчанию в остальной части
C. промежуточные дела => решать по каждому делу по мере необходимости
источник