Некоторые люди рассматривают несколько операторов возврата как плохой стиль программирования. В то время как это верно для больших методов, я не уверен, приемлемо ли это для коротких. Но существует другой вопрос: Если else
явно будьте записаны, если существует оператор возврата в предыдущем if
?
Неявный 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;
}
Какой Вы предпочли бы?Другие рекомендации?
Считать "плохой стиль" множественными операторами возврата - это давно и давно дискредитируемое заблуждение.Они могут сделать код более понятным и более удобным в обслуживании, чем явные переменные возвращаемого значения. Особенно в более крупных методах.
В вашем примере я бы назвал второй вариант наиболее чистым, потому что симметричная структура кода отражает его семантику, а она короче и позволяет избежать ненужных переменных.
Другое очевидное предложение: используйте условный оператор.
private String resolveViewName(Viewable viewable) {
return viewable.isTemplateNameAbsolute()
? viewable.getTemplateName()
: uriInfo.getMatchedResources().get(0).getClass().toString();
}
В случаях, когда это нецелесообразно, я почти наверняка не согласен. Честно говоря, я бы не стал особо переживать по этому поводу - это не та вещь, где читаемость в любом случае может существенно пострадать, и вряд ли это приведет к ошибкам.
(С другой стороны, я бы предложил использовать фигурные скобки для всех if
блоков, даже для блоков с одним оператором.)
Догма «единой точки выхода» пришла со времен структурного программирования.
В свое время структурированное программирование было ХОРОШО, особенно как альтернатива спагетти-коду, основанному на GOTO, который был распространен в старинном коде Fortran и Cobol 1960-х и 1970-х годов. Но с ростом популярности таких языков, как Паскаль, 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";
На первый взгляд кажется, что результатом будет «Привет снова», если i
меньше 10, а j
больше 10. Фактически, то есть неправильное прочтение - нас обманули неправильным отступом.Но если бы код был написан с помощью {}
вокруг тогдашних частей, было бы ясно, что отступ был неправильным; например
String result = "Hello"
if (i < 10) {
result = "Goodbye";
}
if (j > 10) {
result = "Hello again";
}
Как видите, первый }
выделяется, как больной палец, и говорит нам не доверять отступы как визуальный сигнал того, что означает код.
Конечно, люди могут многое сказать о стиле программирования, но не беспокойтесь о чем-то относительно тривиальном для цели вашей программы.
Лично мне нравится обходиться без остального. Если кто-то просматривает ваш код, велики шансы, что он не слишком запутается без else.
Я предпочитаю первый.
Или ... вы можете использовать if return else return
для столь же важных бифуркаций и if return return
для особых случаев.
Когда у вас есть утверждения ( if p == null return null
), то первое из них на сегодняшний день является наиболее ясным. Если у вас есть варианты с одинаковым весом ... Я считаю, что можно использовать явное else.
Это полностью вопрос личных предпочтений - я буквально прошел этапы выполнения всех 4 из этих вариантов (включая тот, который опубликовал Джон Скит) - ни один из них не был неправильным, и я никогда не испытывал никаких недостатков в качестве результат использования любого из них.
Поддерживайте единообразие языка и его удобочитаемость для программиста с наименьшим общим обозначением, которому, возможно, придется пересмотреть код в будущем.
Это всего лишь несколько дополнительных букв для ввода else, и это не имеет никакого значения, кроме удобочитаемости.
Я обычно предпочитаю первый вариант, так как он самый короткий.
И я думаю, что любой порядочный программист должен понимать, как это работает, без необходимости писать else или использовать единственный возврат в конце.
Кроме того, в длинных методах есть случаи, когда вам может потребоваться сделать что-то вроде
if(!isValid(input)) { return null; }// or 0, or false, or whatever
// a lot of code here working with input
Я считаю, что это еще более понятно для таких типов методов.
Зависит от намерения. Если первое возвращение - это быстрая помощь, то я бы пошел без else
; если OTOH больше похож на сценарий «верни то или иное», то я бы использовал иначе
. Кроме того, я предпочитаю ранний оператор возврата, а не бесконечно вложенные операторы if
или переменные, которые существуют с единственной целью - запоминать возвращаемое значение. Если бы ваша логика была немного сложной или даже такой, какая она есть сейчас, я бы подумал о том, чтобы поместить два способа генерации возвращаемого значения в специальные функции и использовать if / else для вызова того же.
Поскольку вы просили другие предложения, как насчет
Использовать утверждения или исключения времени выполнения
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;
}
Я предпочитаю самый чистый подход с одним возвратом. Для меня код читабелен, обслуживается и не сбивает с толку. Если завтра вам нужно добавить несколько строк в блок if или else, это будет просто.
1.) Код никогда не должен быть умным.
Сведения об одном операторе возврата относятся к 1970-м годам, когда Дейкстра и Вирт занимались структурным программированием. Они с большим успехом применили его к контрольным структурам, которые теперь обосновались в соответствии с их предписанием - один вход и один выход. Раньше в Фортране было несколько записей в подпрограмме (или, возможно, функции, извините, прошло около 35 лет с тех пор, как я их написал), и это функция, которую я никогда не упускал, на самом деле я не думаю, что когда-либо использовал ее.
Я никогда не сталкивался с этим «правилом» применительно к методам за пределами академических кругов, и я действительно не вижу в этом смысла. По сути, вам нужно значительно запутать свой код, чтобы подчиниться правилу, с дополнительными переменными и т. Д., И вы никак не можете убедить меня, что это хорошая идея. Как ни странно, если вы напишете его естественным образом в соответствии с вашим первым вариантом, компилятор в любом случае обычно генерирует код в соответствии с правилом ... так что вы можете утверждать, что правило соблюдается: только не вами; -)
Я предпочитаю второй вариант, потому что я считаю его наиболее быстрым для чтения.
Я бы избегал третьего варианта, потому что он не добавляет ясности или эффективности.
Первый вариант тоже хорош, но, по крайней мере, я бы поместил пустую строку между первым битом (if и его возврат с отступом) и вторым оператором return.
В конце концов, все сводится к личным предпочтениям (как и многое другое в стиле программирования).
Я предпочитаю множественные возвраты в структуре if-else, когда размер обоих операторов примерно равен, код выглядит больше сбалансировано таким образом. Для коротких выражений я использую тернарный оператор. Если код для одного теста намного короче или является исключительным случаем, я могу использовать одно if, а остальной код остается в теле метода.
Я стараюсь по возможности избегать изменения переменных, потому что считаю, что это усложняет отслеживание кода, чем несколько выходов из метода.