Самый читаемый способ форматирования длинных условий? [закрыто]

43

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

if (FoobarBaz::quxQuux(corge, grault) || !garply(waldo) || fred(plugh) !== xyzzy) {
    thud();
}

или

if (
    FoobarBaz::quxQuux(corge, grault)
 || !garply(waldo)
 || fred(plugh) !== xyzzy
) {
    thud();
}

или

if (FoobarBaz::quxQuux(corge, grault)
    || !garply(waldo)
    || fred(plugh) !== xyzzy) {
    thud();
}

или

thudable = FoobarBaz::quxQuux(corge, grault);
thudable ||= !garply(waldo);
thudable ||= fred(plugh) !== xyzzy;

if (thudable) {
    thud();
}

или какие-то другие предпочтения?

deceze
источник

Ответы:

30

Часто длинное условие if является признаком кода, который требует рефакторинга, но иногда вы не можете избежать этого. В этих случаях я предпочитаю первое:

if (bar || baz || quux) { ... }

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

function foo() {
  return bar || baz || quux;
}

if (foo()) { ... }
Дориан
источник
3
прокрутка в сторону против вертикали - это не то ограничение, которое было в старые добрые времена ...
Билл
2
и дать значимое (служебное) имя функции, чтобы люди понимали, что здесь тестируется.
Матье М.
20

Мне нравится держать операторов в конце, чтобы указать продолжение:

if (the_function_being_called() != RETURNCODE_SUCCESS &&
    the_possibly_useful_recovery_strategy() == RETURNCODE_EPICFAIL &&
    this_user_has_elected_to_recieve_error_reports)
{
    report_error();
}
AShelly
источник
1
Я думаю, что мне нравится этот. Я использую много скобок, чтобы убедиться, что я тоже могу понять порядок старшинства.
Jasarien
5
Я предпочитаю помещать логические операторы в начало строки, чтобы, читая строку, я мог легко увидеть, что она является частью условной, а не просто обычной строкой кода.
11

Я большой поклонник значимых имен переменных:

const bool isInAStrangeCondition =
    FoobarBaz::quxQuux(corge, grault) ||
    !garply(waldo) ||
    fred(plugh) !== xyzzy;

if (isInAStrangeCondition) {
    thud();
}

Или рефакторинг как функция, как указано выше.

LennyProgrammers
источник
7

Я выделяю более сложные подвыражения или все они как переменные типа bool. Тогда логическая логика верхнего уровня оператора if может быть понятна. В той работе, которую я выполняю, это не всегда несколько вещей: ORed или ANDed.

bool goodblah = some_mess < whatever;
bool frobnacious = messy_crud != junky_expression;
bool yetanother = long_winded_condition;

if (goodblah || (frobnacious && yetanother))   {
    ...
}

Это особенно хорошо в отладчике, где я могу посмотреть все bools перед выполнением 'if'.

DarenW
источник
Мне это тоже нравится, но вы теряете одно преимущество: больше невозможно замкнуть дорогостоящие сравнения.
... И вам нужно хорошо
разбираться
6

Я склоняюсь к выравниванию операторов в начале новых строк, поэтому я помню, как я комбинирую термины (как для длинной логики, так и для длинной арифметики). Так:

if (first_attempt(data) == SUCCESS
    || (reusable(data) && second_attempt(data) == SUCCESS)
    || (still_reusable(data) && third_attempt(data) == SUCCESS))
  return SUCCESS;

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

Хоа Лонг Там
источник
0

Я фанат следующего:

if (really_long_expression && another_really_really_long_expression && 
            another_very_long_expression_OMG_id_it_long){
    bugs();
}

Таким образом, оно по-прежнему выглядит как выражение if, а не как разбитое на части выражение if. Отступ помогает показать, что это продолжение предыдущей строки.

Вы также можете сделать отступ до тех пор, пока открывающая скобка не окажется в конце предыдущей строки, чтобы она была в конце выражения if, как и должно быть.

EpsilonVector
источник
1
Мне очень понравился ваш метод ошибок (): D
Джо Филлипс