Тернарная операция на Java - это не злоупотребление?

Я думаю, что нижеприведенный код трудно понять. Я также чувствую, что он злоупотребляет тернарным оператором Java.

String name = ((this.getAllNamesAsDelimitedString().contains(incomingName) ? 
               incomingName:
               (CollectionsUtils.isEmptyCollection(this.getEntityOperationMap()) ? 
               null : 
               this.getEntityOperationMap.get(incomingName))));

Выше getAllNamesAsDelimitedString будет возвращать запятую (,) с разделителем String.

Я бы предпочел что-то вместо такого вложенного тернарного оператора, если он выглядит более чистым и понятным. Также было бы легко разобраться в проблеме слияния, например, в SVN.

N.B: В коде, который я только что захватил, есть еще более вложенные тернарные условия.

Существует ли какое-либо общее руководство, которое предполагает количество уровней, которые должен допускать тернарный оператор? Другими словами, любое руководство, предлагающее, когда вы должны разорвать свой тернарный оператор для лучшей удобочитаемости кода?

46 голосов | спросил mprabhat 5 MonEurope/Moscow2011-12-05T10:02:50+04:00Europe/Moscow12bEurope/MoscowMon, 05 Dec 2011 10:02:50 +0400 2011, 10:02:50

4 ответа


48

Да, это злоупотребление.

Вообще говоря, я вижу две точки в вашем коде, где вы вывели значение, основанное на базовых структурах данных, которые - если бы они были изменены - также должны были бы измениться.

Кроме того, эти типы вызовов (getAllNamesAsDelimitedString().contains(incomingName) и (CollectionsUtils.isEmptyCollection(this.getEntityOperationMap()), как правило, в конечном итоге используются многие раз, что приводит к сухим результатам.

Кроме того, (this.getAllNamesAsDelimitedString().contains(incomingName) нарушает закон demeter (имеет две точки) и предоставляет то, что я предполагаю, является базовым набором объектов в виде строки , без уважительной причины.

Следовательно, сначала я изменил бы (this.getAllNamesAsDelimitedString().contains(incomingName) на this.containsName(incomingName)

Что делает утверждение:

String name = ((containsName(incomingName)) ? incomingName:
               (CollectionsUtils.isEmptyCollection(this.getEntityOperationMap()) ? 
               null : 
               this.getEntityOperationMap.get(incomingName))));

Только немного лучше.

Я бы применил один и тот же рефакторинг к следующему ттерналу, введя метод hasOperations:

 private boolean hasOperations()
 {
     return !CollectionUtils.isEmptyCollection(this.getEntityOperationMap())
 }

Что теперь делает утверждение:

String name = ((containsName(incomingName)) ? incomingName:
               hasOperations() ? this.getEntityOperationMap.get(incomingName)) : null;

Опять же, немного лучше, но все же неприятно.

Наконец, я бы заменил это на реальный if..then

 private String getName(String incomingName)
 {
     if (containsName(incomingName))
        return incomingName;
     else 
        return hasOperations() ? getOperation(incomingName) : null;
 }
ответил Marty Pitt 5 MonEurope/Moscow2011-12-05T10:55:11+04:00Europe/Moscow12bEurope/MoscowMon, 05 Dec 2011 10:55:11 +0400 2011, 10:55:11
57

Я думаю, что важно отметить, что вложенные троичные операторы могут отформатировать, чтобы хорошо выглядеть:

String name = isConditionA ? "first"
            : isConditionB ? "second"
            : isConditionC ? "third"
                           : "fourth";

Это не самый читаемый вариант в вашем случае, потому что у вас более длинные вызовы методов, но я думаю, что лучше, когда условия остаются короткими и значимыми.

ответил seand 6 TueEurope/Moscow2011-12-06T04:06:17+04:00Europe/Moscow12bEurope/MoscowTue, 06 Dec 2011 04:06:17 +0400 2011, 04:06:17
6

По-моему, я хотел бы получить больше четкости кода, чем использование критических трёхмерных операций. В тех случаях, когда тернарные операторские заявления трудно понять с первого взгляда, идеальное бытие. И кроме того, я не знаю каких-либо различий в производительности приложения, используя тройные операторы. В примере с кодом: требуется некоторое время, чтобы выяснить, что происходит с тернарным оператором, и даже с правильным отступом код не будет таким же очевидным, как при if ... else.

Может быть, вы могли бы воспользоваться соответствующей дискуссией здесь .

ответил sana 5 MonEurope/Moscow2011-12-05T10:50:15+04:00Europe/Moscow12bEurope/MoscowMon, 05 Dec 2011 10:50:15 +0400 2011, 10:50:15
3

Я полностью согласен с user @seand - форматирование делает всю разницу в мире. Я не думаю, что ваш пример - это злоупотребление вообще, но я думаю, что было бы легче следовать с небольшими изменениями ...

Сначала удалите ненужные круглые скобки:

String name = this.getAllNamesAsDelimitedString().contains(incomingName) ? 
              incomingName:
              CollectionsUtils.isEmptyCollection(this.getEntityOperationMap() ? 
              null : 
              this.getEntityOperationMap.get(incomingName);

Затем переформатируйте дерево тройных выражений, как это показано в @seand:

String name = this.getAllNamesAsDelimitedString().contains(incomingName) ? incomingName
            : CollectionsUtils.isEmptyCollection(this.getEntityOperationMap() ? null
            : this.getEntityOperationMap.get(incomingName);

Я часто нахожу более читаемым, чтобы поместить ? и : сразу после их предыдущего символа - без промежуточных пробелов - как если бы они были английскими знаки препинания:

String name = isConditionA? "first":
              isConditionB? "second":
              isConditionC? "third":
                            "fourth";

, который дал бы:

String name = this.getAllNamesAsDelimitedString().contains(incomingName)? incomingName:
              CollectionsUtils.isEmptyCollection(this.getEntityOperationMap()? null:
              this.getEntityOperationMap.get(incomingName);

Но в этом случае я, вероятно, напишу вот так:

String name =
    this.getAllNamesAsDelimitedString().contains(incomingName)
        ? incomingName
        : CollectionsUtils.isEmptyCollection(this.getEntityOperationMap()
            ? null
            : this.getEntityOperationMap.get(incomingName);
ответил Todd Lehman 22 Jam1000000amSun, 22 Jan 2012 11:51:11 +040012 2012, 11:51:11

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132