Использование троичного оператора с 4 выражениями
-
06-07-2019 - |
Вопрос
Это приемлемая практика кодирования?
public class MessageFormat {
private static final Color DEFAULT_COLOR = Color.RED;
private Color messageColor = DEFAULT_COLOR;
public MessageFormat(Person person) {
Color color = person.getPreferredColor();
messageColor = (color != null) ? color : messageColor; // this line
}
}
или мне лучше пойти с классическим ...
if (color != null) {
messageColor = color;
}
Решение
Использование оператора?: должно быть ограничено, чтобы сделать код более читабельным. Классический пример:
a = sprintf( "There are %i green bottle%s on the wall.", i, (i==1?"":"s") );
В этом случае код будет менее читабельным, если разбить его на 5 строк if / else.
Я обычно ставлю скобки вокруг всего оператора, чтобы при чтении я мысленно анализировал его как одно значение.
messageColor = (color != null ? color : messageColor);
Другой вариант -
messageColor = color || messageColor;
Который на некоторых языках будет оцениваться как «цвет», если только цвет не оценивается как «ложный», в этом случае значение messageColor. На мой взгляд, этого следует избегать, так как это может смутить людей.
Самое главное - быть последовательным, чтобы у следующего человека, читающего ваш код (даже если это вы), были минимальные когнитивные издержки. Р>
Другие советы
Читаемость, простота понимания и т. д. в этом случае одинаковы (я имею в виду, давай ... ). Мне не нравится дублирование и очевидное самоопределение в первом примере; это будет означать что-то вроде:
if (colour != null) {messageColour = colour;}
else {messageColour = messageColour;};
что немного глупо.
Обычно я пишу второе в одной строке, но это вопрос индивидуальной фантазии, соответственно. рекомендации по стилю кодирования:
if (colour != null) {messageColour = colour;};
РЕДАКТИРОВАТЬ (сейчас я более самоуверен, чем 8 лет назад)
Поскольку вы ищете лучшие практики:
// Use default visibility by default, especially in examples.
// Public needs a reason.
class MessageFormat {
static final Color DEFAULT_COLOR = Color.RED;
// Strongly prefer final fields.
private final Color messageColor;
// Protect parameters and variables against abuse by other Java developers
MessageFormat (final Person person) {
// Use Optionals; null is a code smell
final Optional<Color> preferredColor = person.getPreferredColor();
// Bask in the clarity of the message
this.messageColor = preferredColor.orElse(DEFAULT_COLOR);
}
}
Использование троичного оператора часто является деликатным вопросом наряду с другими стандартами кодирования. Его использование, вероятно, лучше всего определяется стандартами кодирования на вашем сайте.
Однако в этой конкретной ситуации я бы определенно рекомендовал второй вариант; это не только более понятно, но и использование тернарного оператора здесь совершенно не нужно. Нет необходимости переназначать messageColor для себя, поэтому единственной функцией троичного оператора в этой конкретной ситуации является запутывание кода.
Тернарный оператор более распространен среди программистов на Си. В C, если вы избегаете управляющих структур, вы можете получить лучшую конвейерную работу, так как нет предсказания ветвления, которое могло бы пойти не так. Я сомневаюсь, что вы увидите какие-либо различия в производительности в Java, и шаблон if-null-then-assign гораздо более распространен, чем троичный. Однако, если вы поддерживаете существующую кодовую базу, обычно лучше оставаться в соответствии с существующим кодом.
Если вы часто этим занимаетесь, вы можете написать функцию defaultIfNull
, firstNonNull
или coalesce
, которая может сделать код еще более кратким. Apache Commons Lang включает функцию defaultIfNull
.
В некоторых языках есть оператор || =
, который является обычной идиомой для значений по умолчанию в этих языках. Р>
Я предпочитаю второе, потому что оно более четко выражает то, что вы имеете в виду: вы хотите изменить цвет, только если он не нулевой. Первый метод не делает это настолько ясным.
В вашем случае я бы предпочел «классическую» реализацию, потому что для меня быстрее понять, что вы хотите использовать новый цвет, только если у человека есть предпочтительный.
Я иногда использую его в вызовах методов, если я хочу избежать NPE, но я обычно выявляю эти уродливые фрагменты кода в одном из следующих рефакторингов;)
Тернарные операторы часто подвергаются злоупотреблениям, поскольку код, который они создают, кажется умным и компактным.
Фактически они делают код менее читаемым и более подверженным ошибкам. По возможности рекомендуется использовать более длинную версию
if ( <condition> ) {
<action> ;
}
Вместо троичного синтаксиса.
Мне кажется, это нормально (я часто использую троичный оператор Python), но этот тип стилей обычно очень субъективен. Если у проекта есть документ в стиле кодирования, вы можете проверить это.