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


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();
}

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

Ответы:


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();
}

1
Я думаю, что мне нравится этот. Я использую много скобок, чтобы убедиться, что я тоже могу понять порядок старшинства.
Jasarien

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

11

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

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

if (isInAStrangeCondition) {
    thud();
}

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


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'.


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

... И вам нужно хорошо
разбираться

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, как и должно быть.


1
Мне очень понравился ваш метод ошибок (): D
Джо Филлипс
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.