Почему "else" редко используется после "if x then return"?
этот метод:
boolean containsSmiley(String s) {
if (s == null) {
return false;
}
else {
return s.contains(":)");
}
}
можно эквивалентно написать:
boolean containsSmiley(String s) {
if (s == null) {
return false;
}
return s.contains(":)");
}
(связанных с: должна ли функция иметь только один оператор return?)
23 ответов:
По моему опыту, это зависит от кода. Если я "охраняю" от чего-то, я сделаю:
if (inputVar.isBad()) { return; } doThings();суть ясна: если это утверждение ложно, я не хочу, чтобы функция, чтобы продолжать.
С другой стороны, есть некоторые функции с несколькими параметрами и в этом случае я бы написал так:
if (inputVar == thingOne) { doFirstThing(); } else if (inputVar == secondThing) { doSecondThing(); } else { doThirdThing(); }хотя это может быть написано как:
if (inputVar == thingOne) { doFirstThing(); return; } if (inputVar == thingTwo) { doSecondThing(); return; } doThingThree(); return;Это действительно сводится к тому, какой путь наиболее наглядно показывает, что код делает (не обязательно, какой бит кода является самым коротким или имеет наименьший отступ).
на
elseв этом случае будут лишними, а также создавать ненужные дополнительные отступы для основного кода функции.
это шаблон называется Пункт Охраны. Идея состоит в том, чтобы сделать все проверки заранее, чтобы уменьшить вложенные условия для повышения читаемости.
из ссылки:
double getPayAmount() { double result; if (_isDead) { result = deadAmount(); } else { if (_isSeparated) { result = separatedAmount(); } else { if (_isRetired) { result = retiredAmount(); } else { result = normalPayAmount(); } } } return result; }используя предложение Guard, вы увидите этот результат:
double getPayAmount() { if (_isDead) return deadAmount(); if (_isSeparated) return separatedAmount(); if (_isRetired) return retiredAmount(); return normalPayAmount(); };
вы увидите это повсюду:
if (condition) { return var; } // by nature, when execution reaches this point, condition can only be false, // therefore, the else is unnecessary return other_var;В большинстве случаев добавление предложения else не только не нужно в этом случае, но и много раз, он получает оптимизировать компилятором.
подумайте, как компьютер думает об этом коде (в терминах машинного кода, упрощенного в псевдокод здесь для демонстрационных целей):
0x00: test [condition] 0x01: if result of test was not true, goto [0x04] 0x02: push [var] onto stack 0x03: goto [0x05] 0x04: push [other_var] onto stack 0x05: return from subroutineкод (опять же, это псевдокод, а не сборка) будет действовать точно так же для
if/then/elseусловное.многие люди считают плохой и / или запутанной практикой иметь несколько возможных точек выхода для функции, поскольку программист должен думать о каждом возможном пути через свой код. Другая практика заключается в следующем:
return (condition) ? var : other_var;это упрощает код и не создает никаких новых точек выхода.
Я предпочитаю писать так:
boolean containsSmiley(String s) { return s != null && s.contains(":)"); }
Как и любое "обсуждение" о стилях кодирования нет правильного ответа. Я предпочитаю применять следующие соображения:
работает код, как ожидалось во всех ситуациях. (Принцип наименьшего удивления)
может ли следующий разработчик (я или кто-то другой) понять, что он делает и почему.
насколько хрупок код по отношению к изменению.
- Это просто, как это должно быть и не более. То есть нет над или под инженерией.
Как только я счастлив, что я удовлетворил выше, остальное, как правило, просто падает в линию.
кто-то еще, вероятно, уже заметил это, но я бы рекомендовал не использовать нулевые значения вообще, где ожидаются строки. Если вы действительно хотите проверить, чтобы кто-то не передавал нулевые значения, вы можете использовать asserts (во время разработки) или модульные тесты (развертывание):
boolean containsSmiley(String s) { assert s != null : "Quit passing null values, you moron."; return s.contains(":)"); }я перешел к общему правилу: Никогда. Когда-либо. передайте значения null, если внешний API-вызов явно не запрашивает его. Во-вторых: если внешний метод может возвращать нулевые значения, замените его разумным ненулевое значение (например, пустая строка) или добавить аккуратную проверку. Меня тошнит от повторяющихся
if (thing == null)проверка.но это немного оффтоп. Мне нравится ставить короткие условия сверху и охранять предложения, удаляя elses, если поток программы диктует, что он никогда не доберется туда.
это Религиозный аргумент, и в конце концов это не имеет значения. Я бы даже сказал, что первая форма более читаема в некоторых обстоятельствах. Если у вас есть большие куски кода
if-elseif-elseif-else, это проще, на первый взгляд, чтобы увидеть, что такое возврат по умолчанию.if (s == null) { return false; } else if (s.Contains(":))")) { return true; } else if (s.Contains(":-(")) { return false; } return s.contains(":)");
Бритва Оккама это принцип, что "сущности не должны умножаться сверх необходимости."
на
ifоператор проверяет / применяет ваш контракт / ожидание не получения нулевых значений. По этой причине я предпочел бы видеть его отделенным от остальной части функции, поскольку он не имеет ничего общего с фактической логикой того, что вы пытаетесь выполнить (хотя этот случай очень прост).в большинстве случаев, однако, я предпочитаю, чтобы код был как можно более явным в своем намерении. Если есть что-то, что вы можете реструктурировать в своей функции, чтобы сделать это более читаемый для других, сделайте это. Как профессиональный программист, ваша цель должна быть действительно программа для тех, кто должен поддерживать ваш код после вас (включая себя спустя 2 года...). Все, что вы можете сделать, чтобы помочь им, стоит сделать.
на
elseизбыточна. Также некоторые IDE (Eclipse) и инструменты анализа (возможно, FindBugs) могут помечать это как предупреждение или ошибку, поэтому в этом случае программисты, скорее всего, удалят его.
потому что это приятнее. Вы знаете, что вы также можете использовать '{' '}' для создания нескольких уровней вложенности, но никто не делает это просто так.
Я бы предпочел первый вариант, так как он более читаемый.
в качестве аналогии сравните следующие 2 предложения: "если сегодня идет дождь, то возьмите зонтик, иначе возьмите солнцезащитные очки. и "если сегодня идет дождь, то возьмите зонтик, возьмите солнцезащитные очки". Первое предложение соответствует первому блоку кода из вопроса, второе – второму. Первый гораздо более понятен и читаем, не так ли?
первая форма просто менее подробна - когда вы возвращаете значение, вы автоматически покидаете область действия функции, в которой вы находитесь, и возвращаетесь к вызывающему, поэтому любой код после этого будет выполняться только в том случае, если оператор IF не оценивает значение true и впоследствии возвращает что-либо.
Я бы поспорил, для удобочитаемости. Если вы сканируете экраны кода, пытаясь выяснить, что делает код, это визуальное приглашение разработчику.
...но это действительно не нужно, потому что мы все так хорошо комментируем наш код, верно? :)
на мой взгляд, второй имеет больше смысла. Он служит скорее действием "по умолчанию", как переключатель. Если он не соответствует ни одной из других точек выхода, то сделайте это. Вам действительно не нужно еще там. Я бы сказал, что если вся функция только если и elseif, то еще будет иметь смысл там, потому что это один гигантский условный. Если в нем выполняется несколько условных выражений и других функций, то в конце будет использоваться возврат по умолчанию.
хотя наличие else является правильным, и в этом нет ничего плохого с точки зрения логики и управляемости, мне нравится избегать начального момента WTF, когда функция не имеет оператора return за пределами области if/else.
Как вы можете видеть, разные люди имеют разные мнения о читаемости. Некоторые люди думают, что меньшее количество строк кода, как правило, делает код более читаемым. Другие считают, что симметрия второй формы делает ее более читаемой.
Я считаю, что, вероятно, оба мнения верны ... для людей, которые их держат. И следствием этого является то, что вы не можете написать код, который каждый находит оптимально читаемым. Итак, лучший совет-следовать тому, что ваш обязательный стандарт кодирования говорит делать (если он говорит что-нибудь об этом) и вообще использовать свой здравый смысл. (Если вы обременены каким-то громогласным придурком, который настаивает на том, что его путь "правильный" ... просто плыви по течению.)
потому что в eclipse есть дополнительное (выключенное по умолчанию) предупреждение, если в такой ситуации используется else ;).
Ну, некоторые из причин-это просто конвенция, но есть одно достоинство в данной формы...
Это типично при кодировании оператора return, чтобы сделать последний оператор возвращаемым значением по умолчанию. Это в первую очередь помогает во время рефакторинга - другие предложения, как правило, завернуты в другие структуры или могут случайно быть перемещены глубже в дерево.
Я бы предпочел одну точку выхода над несколькими с точки зрения обслуживания. Конечный результат может быть изменен (или украшен) в одной точке выхода, а не в n точках выхода.
вторая форма, если проще/короче. Это не всегда означает четкое. Я предлагаю вам сделать то, что вы считаете наиболее ясным.. Лично я бы написал.
static boolean containsSmiley(String s) { return s != null && s.contains(":)"); }
потому что это то же самое, что написать одно из следующих, которое приносит доказательства о намерении программиста:
boolean containsSmiley(String s) { if (s == null) // The curly braces are not even necessary as the if contains only one instruction. return false; return s.contains(":)"); }или даже так:
boolean constainsSMiley(String s) { return string.IsNullOrEmpty(s) ? false : s.Contains(":)"); }эти две формы являются:
- более элегантным;
- легче читать;
- более сухопарый и более быстрый для программиста чтения.
Comments