Как вы справляетесь с огромными if-условиями? - PullRequest
28 голосов
/ 08 августа 2008

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

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

Пример, все в одной строке:

if (var1 = true && var2 = true && var2 = true && var3 = true && var4 = true && var5 = true && var6 = true)
{

Пример, многострочный:

if (var1 = true && var2 = true && var2 = true
 && var3 = true && var4 = true && var5 = true
 && var6 = true)
{

Пример вложенный:

if (var1 = true && var2 = true && var2 = true && var3 = true)
{
     if (var4 = true && var5 = true && var6 = true)
     {

Ответы [ 21 ]

1 голос
/ 08 августа 2008

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

1 голос
/ 08 августа 2008

Я прибегаю к отдельным логическим значениям:

Bool cond1 == (var1 && var2);
Bool cond2 == (var3 && var4);

if ( cond1 && cond2 ) {}
1 голос
/ 09 мая 2010

В рефлексивных языках, таких как PHP, вы можете использовать переменные-переменные:

$vars = array('var1', 'var2', ... etc.);
foreach ($vars as $v)
    if ($$v == true) {
        // do something
        break;
    }
0 голосов
/ 15 октября 2008

Если бы я делал это в Perl, я мог бы выполнять проверки.

{
  last unless $var1;
  last unless $var2;
  last unless $var3;
  last unless $var4;
  last unless $var5;
  last unless $var6;

  ... # Place Code Here
}

Если вы планируете использовать это в подпрограмме, замените каждый экземпляр last на return;

0 голосов
/ 18 августа 2008

Мне нравится разбивать каждое условие на описательные переменные.

bool isVar1Valid, isVar2Valid, isVar3Valid, isVar4Valid;
isVar1Valid = ( var1 == 1 )
isVar2Valid = ( var2.Count >= 2 )
isVar3Valid = ( var3 != null )
isVar4Valid = ( var4 != null && var4.IsEmpty() == false )
if ( isVar1Valid && isVar2Valid && isVar3Valid && isVar4Valid ) {
     //do code
}
0 голосов
/ 08 августа 2008

@ tweakt

Не лучше, но то, что я делал в прошлом:

boolean ok = cond1; хорошо & = cond2; хорошо & = cond3; хорошо & = cond4; хорошо & = cond5; хорошо & = cond6;

Что совпадает с:

ok = (cond1 && cond2 && cond3 && cond4 && cond5 && cond6);

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

Для удобства чтения я лично предпочитаю предложение Майка Стоуна выше. Легко комментировать подробно и сохраняет все вычислительные преимущества возможности раннего запуска. Вы также можете сделать ту же технику встроенной в функцию, если это помешает организации вашего кода отодвинуть условную оценку от вашей другой функции. Это немного глупо, но вы всегда можете сделать что-то вроде:

do {
    if (!cond1)
       break;
    if (!cond2)
       break;
    if (!cond3)
       break;
    ...
    DoSomething();
} while (false);

while (false) отчасти глупо. Мне бы хотелось, чтобы у языков был оператор видимости, называемый «один раз», или что-то такое, из чего вы могли бы легко выйти.

0 голосов
/ 08 августа 2008

Макдауэлл,

Вы правы в том, что при использовании одного оператора '&' вычисляются обе стороны выражения. Однако при использовании оператора '&&' (по крайней мере, в C #) первое выражение, возвращающее false, является последним вычисленным выражением. Это делает размещение выражения перед оператором FOR таким же хорошим, как и любой другой способ сделать это.

0 голосов
/ 08 августа 2008

Если вы сделаете это:

if (var1 == true) {
    if (var2 == true) {
        if (var3 == true) {
            ...
        }
    }
}

Тогда вы также можете реагировать на случаи, когда что-то не так. Например, если вы проверяете ввод, вы можете дать пользователю подсказку о том, как правильно его отформатировать, или как угодно.

0 голосов
/ 08 августа 2008

Мне нравится разбивать их по уровням, поэтому я отформатирую ваш пример так:

if (var1 = true
 && var2 = true
 && var2 = true
 && var3 = true
 && var4 = true
 && var5 = true
 && var6 = true){

Это удобно, когда у вас больше вложенности, как это (очевидно, реальные условия были бы более интересны, чем "= true" для всего):

if ((var1 = true && var2 = true)
 && ((var2 = true && var3 = true)
  && (var4 = true && var5 = true))
 && (var6 = true)){
0 голосов
/ 03 мая 2017
    if (   (condition_A)
        && (condition_B)
        && (condition_C)
        && (condition_D)
        && (condition_E)
        && (condition_F)
       )
    {
       ...
    }

в отличие от

    if (condition_A) {
       if (condition_B) {
          if (condition_C) {
             if (condition_D) {
                if (condition_E) {
                   if (condition_F) {
                      ...
                   }
                }
             }
          }
       }
    }

и

    if (   (   (condition_A)
            && (condition_B)
           )
        || (   (condition_C)
            && (condition_D)
           )
        || (   (condition_E)
            && (condition_F)
           )
       )
    {
       do_this_same_thing();
    }

в отличие от

    if (condition_A && condition_B) {
       do_this_same_thing();
    }
    if (condition_C && (condition_D) {
       do_this_same_thing();
    }
    if (condition_E && condition_F) {
       do_this_same_thing();
    }

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

Вертикальное выравнивание на одном и том же уровне отступа открытых / закрытых скобок {}, открытых закрывающих скобок (), условных выражений с круглыми скобками и операторов слева - очень полезная практика, которая значительно повышает удобочитаемость и ясность кода в отличие от для заклинивания всего, что может быть зажато в одну строку, без вертикального выравнивания, пробелов или скобок

Правила приоритета операторов хитры, например, && имеет более высокий приоритет, чем ||, но | имеет приоритет перед &&

Итак, ...

    if (expr_A & expr_B || expr_C | expr_D & expr_E || expr_E && expr_F & expr_G || expr_H {
    }

- это действительно простое множественное условное выражение, которое простые люди могут читать и оценивать неправильно.

    if (   (  (expr_A)
            & (expr_B)
           )
        || (  (expr_C)
            | (  (expr_D)
               & (expr_E)
              )
           )
        || (   (expr_E)
            && (  (expr_F)
                & (expr_G)
               )
           )
        || (expr_H)
       )
    {
    }

Нет ничего плохого в горизонтальном пространстве (переводы строк), вертикальном выравнивании или явной скобке, определяющей оценку выражений, все из которых УЛУЧШАЕТ читабельность и ясность

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...