Возврат из метода с неявным или явным "else" или с помощью одного выражения "return"?
Некоторые люди рассматривают несколько операторов возврата как плохой стиль программирования. Хотя это справедливо для более крупных методов, я не уверен, что это приемлемо для коротких. Но есть еще один вопрос: следует ли явно выражать else
, если в предыдущем if
есть оператор return?
Неявный else
:
private String resolveViewName(Viewable viewable) {
if(viewable.isTemplateNameAbsolute())
return viewable.getTemplateName();
return uriInfo.getMatchedResources().get(0).getClass().toString();
}
Явный else
:
private String resolveViewName(Viewable viewable) {
if(viewable.isTemplateNameAbsolute())
return viewable.getTemplateName();
else
return uriInfo.getMatchedResources().get(0).getClass().toString();
}
Технически else
здесь не требуется, но это делает смысл более очевидным.
И, возможно, самый чистый подход с одним возвратом:
private String resolveViewName(Viewable viewable) {
String templateName;
if(viewable.isTemplateNameAbsolute())
templateName = viewable.getTemplateName();
else
templateName = uriInfo.getMatchedResources().get(0).getClass().toString();
return templateName;
}
Какой из них вы бы предпочли? Другие предложения?
Ответы
Ответ 1
Другое очевидное предположение: используйте условный оператор.
private String resolveViewName(Viewable viewable) {
return viewable.isTemplateNameAbsolute()
? viewable.getTemplateName()
: uriInfo.getMatchedResources().get(0).getClass().toString();
}
В случаях, когда это нежизнеспособно, я почти наверняка не согласен. Я бы не стал слишком беспокоиться об этом, если честно - это не та вещь, в которой читабельность похожа на то, что она сильно затронута в любом случае, и вряд ли она представит ошибки.
(С другой стороны, я бы предложил использовать фигурные скобки для всех блоков if
, даже для одного оператора).
Ответ 2
Я предпочитаю самый чистый подход с одним возвратом. Для меня код читабельный, поддерживаемый и не путающий. Завтра, если вам нужно добавить некоторые строки в блок if или else, это будет легко.
1.) код никогда не должен быть умным.
Ответ 3
Догма "единственной точки выхода" исходит из дней структурированного программирования.
В свое время структурированное программирование было ХОРОШЕЙ ВЕЩЕЙ, особенно в качестве альтернативы GOTO-коду спагетти, который был распространен в 1960 и 1970 годах в винтажном коде Fortran и Cobol. Но с популярностью таких языков, как Pascal, C и т.д. С их более богатым спектром структур управления, структурированное программирование было ассимилировано в основное программирование, и некоторые догматические аспекты оказались в немилости. В частности, большинство разработчиков счастливы иметь несколько выходов из цикла или метода... при условии, что это упрощает понимание кода.
Мое личное чувство состоит в том, что в этом конкретном случае симметрия второй альтернативы облегчает понимание, но первая альтернатива почти читаема. Последняя альтернатива называет меня излишней подробностью и наименее читаемой.
Но @Jon Skeet отметил, что с вашим кодом гораздо более значительная стилистическая проблема; т.е. отсутствие {} блоков вокруг операторов "then" и "else". Для меня код действительно должен быть написан следующим образом:
private String resolveViewName(Viewable viewable) {
if (viewable.isTemplateNameAbsolute()) {
return viewable.getTemplateName();
} else {
return uriInfo.getMatchedResources().get(0).getClass().toString();
}
}
Это не просто проблема хорошего кода. На самом деле существует серьезный момент для использования блоков. Рассмотрим это:
String result = "Hello"
if (i < 10)
result = "Goodbye";
if (j > 10)
result = "Hello again";
На первый взгляд похоже, что результат будет "Hello again", если i
меньше 10, а j
больше 10. На самом деле это неверное истолкование - нас обманули неправильным отступом, Но если код был написан с { }
вокруг тех частей, было бы ясно, что отступ был неправильным; например.
String result = "Hello"
if (i < 10) {
result = "Goodbye";
}
if (j > 10) {
result = "Hello again";
}
Как вы видите, первый }
выделяется как больной палец и говорит нам не доверять отступу как визуальный сигнал к тому, что означает код.
Ответ 4
Я обычно предпочитаю первый вариант, так как он самый короткий.
И я думаю, что любой достойный программист должен понять, как это работает без того, чтобы мне пришлось писать другое или использовать один возврат в конце.
Плюс есть случаи в длинных методах, где вам может понадобиться сделать что-то вроде
if(!isValid(input)) { return null; }// or 0, or false, or whatever
// a lot of code here working with input
Я нахожу это более ясным, как это для этих типов методов.
Ответ 5
Зависит от намерения. Если первое возвращение - быстрое спасение, я бы пошел без else
; если OTOH больше похож на сценарий "вернуться или тот или иной", то я бы использовал else
. Кроме того, я предпочитаю оператор раннего возврата для бесконечно вложенных if
операторов или переменных, которые существуют с единственной целью запоминания возвращаемого значения. Если бы ваша логика была немного сложной или даже сейчас, я бы рассмотрел возможность использования двух способов генерации возвращаемого значения в выделенные функции и использовать if/else для вызова.
Ответ 6
Я предпочитаю несколько возвратов в структуре if-else, когда размер обоих операторов примерно одинаковый, код выглядит более сбалансированным таким образом. Для коротких выражений я использую тернарный оператор. Если код для одного теста намного короче или является исключительным случаем, я могу использовать сингл, если остальная часть кода остается в теле метода.
Я стараюсь избегать модификации переменных как можно больше, потому что, по-моему, это делает код намного сложнее, чем несколько выходов из метода.
Ответ 7
Сохраняйте lingo согласованным и читаемым для младшего программиста с общим выражением, которому, возможно, придется пересматривать код в будущем.
Только несколько лишних букв для ввода else и не имеет никакого значения ни к чему, кроме удобочитаемости.
Ответ 8
Я предпочитаю первый.
Или... вы можете использовать if return else return
для одинаково важных бифуркаций и if return return
для особых случаев.
Когда у вас есть утверждения (if p==null return null
), то первый из них наиболее ясен. Если у вас одинаково взвешенные варианты... Я считаю, что использовать явное другое.
Ответ 9
Это полностью вопрос личных предпочтений - я буквально пережил фазы выполнения всех 4 этих вариантов (в том числе один опубликованный Джон Скит) - ни один из них не ошибается, и я никогда не испытывал никаких недостатков, как результат использования любого из них.
Ответ 10
Материал о только одном возвратном заявлении датируется 1970-ми годами, когда Дейкстра и Вирт изучали структурированное программирование. Они применили его с большим успехом для управления структурами, которые теперь располагаются в соответствии с их назначением на одну запись и один выход. У Fortran было несколько записей в подпрограмме (или, возможно, функция, извините, около 35 лет с тех пор, как я их написал), и это функция, которую я никогда не пропускал, действительно, я не думаю, что когда-либо использовал ее.
Я никогда не сталкивался с этим "правилом" применительно к методам вне академических кругов, и я действительно не вижу смысла. Вы в основном должны зафрахтовать свой код, чтобы повиноваться правилу, с дополнительными переменными и так далее, и никоим образом вы не можете убедить меня, что это хорошая идея. Любопытно, что если вы напишете его естественным образом в соответствии с вашим первым вариантом, компилятор обычно генерирует код в соответствии с правилом в любом случае... так что вы можете утверждать, что правило соблюдается: только не вами; -)
Ответ 11
Поскольку вы просили другие предложения, как насчет
Использовать утверждения или RuntimeExceptions
private String resolveViewName(Viewable viewable) {
if(viewable.isTemplateNameAbsolute())
return viewable.getTemplateName();
else
return uriInfo.getMatchedResources().get(0).getClass().toString();
throw new RuntimeException ( "Unreachable Code" ) ;
}
Используйте ключевое слово
private String resolveViewName(Viewable viewable) {
final String templateName;
if(viewable.isTemplateNameAbsolute())
templateName = viewable.getTemplateName();
else
templateName = uriInfo.getMatchedResources().get(0).getClass().toString();
return templateName;
}
Ответ 12
Конечно, людям есть что сказать о стиле программирования, но не беспокойтесь о чем-то относительно тривиальном для вашей цели программы.
Лично мне нравится идти без остального. Если кто-то проходит ваш код, шансы высоки, он не будет слишком смущен без остального.
Ответ 13
Я предпочитаю второй вариант, потому что для меня он самый быстрый для чтения.
Я бы избегал третьего варианта, потому что он не добавляет ясности или эффективности.
Первый вариант тоже хорош, но по крайней мере я бы поставил пустую строку между первым битом (if и его отступом return) и вторым оператором return.
В конце концов, это сводится к личным предпочтениям (как и многие вещи в стиле программирования).
Ответ 14
Учитывая несколько утверждений о возврате "плохой стиль", это долгая, длинная дискредитированная ошибка. Они могут сделать код намного понятным и более удобным, чем явные переменные возвращаемого значения. Особенно в более крупных методах.
В вашем примере я бы рассмотрел второй вариант, самый чистый, потому что симметричная структура кода отражает его семантику, и она короче и позволяет избежать ненужной переменной.