重构复杂的if条件

kum*_*ala 7 java refactoring conditional if-statement

任何人都可以提出最好的方法来避免大多数条件?我有下面的代码,我想避免大多数情况下如果条件,怎么办呢?任何解决方案都很有帮助;

if (adjustment.adjustmentAccount.isIncrease) {
    if (adjustment.increaseVATLine) {
        if (adjustment.vatItem.isSalesType) {
            entry2.setDebit(adjustment.total);
            entry2.setCredit(0d);
        } else {
            entry2.setCredit(adjustment.total);
            entry2.setDebit(0d);
        }
    } else {
        if (adjustment.vatItem.isSalesType) {
            entry2.setCredit(adjustment.total);
            entry2.setDebit(0d);
        } else {
            entry2.setDebit(adjustment.total);
            entry2.setCredit(0d);
        }
    }
} else {
    if (adjustment.increaseVATLine) {
        if (adjustment.vatItem.isSalesType) {
            entry2.setCredit(adjustment.total);
            entry2.setDebit(0d);
        } else {
            entry2.setDebit(adjustment.total);
            entry2.setCredit(0d);
        }
    } else {
        if (adjustment.vatItem.isSalesType) {
            entry2.setDebit(adjustment.total);
            entry2.setCredit(0d);
        } else {
            entry2.setCredit(adjustment.total);
            entry2.setDebit(0d);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Car*_*ter 18

如何解决这个问题......让我们提取几个方法,这样我们就能更好地看到逻辑.

private void a() {
    entry2.setDebit(adjustment.total);
    entry2.setCredit(0d);
}
private void b() {
    entry2.setCredit(adjustment.total);
    entry2.setDebit(0d);
}

if (adjustment.adjustmentAccount.isIncrease) {
    if (adjustment.increaseVATLine) {
        if (adjustment.vatItem.isSalesType) {
            a();
        } else {
            b();
        }
    } else {
        if (adjustment.vatItem.isSalesType) {
            b();
        } else {
            a();
        }
    }
} else {
    if (adjustment.increaseVATLine) {
        if (adjustment.vatItem.isSalesType) {
            b();
        } else {
            a();
    }
} else {
    if (adjustment.vatItem.isSalesType) {
        a();
    } else {
        b();
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,看着它,第一块

if (adjustment.increaseVATLine) {
    if (adjustment.vatItem.isSalesType) {
        a();
    } else {
        b();
    }
} else {
    if (adjustment.vatItem.isSalesType) {
        b();
    } else {
        a();
    }
}
Run Code Online (Sandbox Code Playgroud)

a()如果adjustment.increaseVATLine具有相同的值adjustment.vatItem.isSalesType,那么只是等于b().所以我们可以减少它:

if (adjustment.adjustmentAccount.isIncrease) {
    if (adjustment.increaseVATLine == adjustment.vatItem.isSalesType) {
        a();
    } else {
        b();
    }
} else {
    if (adjustment.increaseVATLine) {
        if (adjustment.vatItem.isSalesType) {
            b();
        } else {
            a();
        }
    } else {
        if (adjustment.vatItem.isSalesType) {
            a();
        } else {
            b();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

剩下的块是相同的,只是反转a()并且b():

if (adjustment.adjustmentAccount.isIncrease) {
    if (adjustment.increaseVATLine == adjustment.vatItem.isSalesType) {
        a();
    } else {
        b();
    }
} else {
    if (adjustment.increaseVATLine == adjustment.vatItem.isSalesType) {
        b();
    } else {
        a();
    }
}
Run Code Online (Sandbox Code Playgroud)

所以我们开始看到逻辑.如果它是一个增加,并且increaseVATLine匹配isSalesType,那么我们借记,否则信用,但如果它是减少,那么我们只有在它们不匹配时才会记入.表达这个的好方法是什么?好吧,对于其中一个,将()和b()命名为更聪明 - 现在我们可以看到他们正在做什么

if (adjustment.adjustmentAccount.isIncrease) {
    if (adjustment.increaseVATLine == adjustment.vatItem.isSalesType) {
        debitEntry();
    } else {
        creditEntry();
    }
} else {
    if (adjustment.increaseVATLine == adjustment.vatItem.isSalesType) {
        creditEntry();
    } else {
        debitEntry();
    }
}
Run Code Online (Sandbox Code Playgroud)

而现在它仍然更加清晰.当帐户是增加帐户和增加的增值税行,销售类型,或者减少时,借记帐户,或者减少增值税行或者是销售类型,但不是两者.这个真相表有帮助吗?第一栏是adjustmentAmount.isIncrease; 第二是adjustment.increaseVATLine; 第三是adjustment.vatItem.isSalesType.第四栏是D代表借方,C代表贷方; 在括号中是标志中的TRUE值的数量.

TTT -> D (3) 
TFF -> D (1) 
TTF -> C (2)
TFT -> C (2) 
FTT -> C (2) 
FFF -> C (0)
FTF -> D (1) 
FFT -> D (1)
Run Code Online (Sandbox Code Playgroud)

现在您可以看到为什么@Xavier Ho的解决方案有效; 奇数总数都是借方,偶数都是贷方.

这只是一条探索之路; 我希望它有用.


Mar*_*tos 8

我还没有彻底验证逻辑,但这是基本的想法:

amt = adjustment.total
if (adjustment.adjustmentAccount.isIncrease
    ^ adjustment.increaseVATLine
    ^ adjustment.vatItem.isSalesType)
{
    amt = -amt;
}

entry2.setCredit(amt > 0 ? amt : 0);
entry2.setDebit(amt < 0 ? -amt : 0);
Run Code Online (Sandbox Code Playgroud)

我应该注意到这个逻辑略有不同,因为它正确地处理了负值adjustment.total,而原始似乎假设(可能正确)该值总是非负的.


kgi*_*kis 6

你可以使用这样的真值表:

debit = ((isIncrease && increaseVATLine && !isSalesType) ||
         (isIncrease && !increaseVATLine && isSalesType) ||
         (!isIncrease && increaseVATLine && isSalesType) ||
         (!isIncrease && !increaseVATLine && !isSalesType)) ? 0 : adjustment.total;
entry2.setCredit(debit);
Run Code Online (Sandbox Code Playgroud)

没有任何ifs,你可以很容易地看到借方是0的情况.信用额度相同.


Xav*_* Ho 6

我觉得这很有效.我基本上概括了你的布尔逻辑.下次,尝试绘制一些图表以帮助您清除头脑.

编辑:我想从本文的评论中指出,Marcelo和BlueRaja提供的XOR解决方案在功能上是相同的.

/* This is to avoid a crazy 3-way switch. Generalised.
 * Instead of using a complicated if-else branch, we can use the number of true
 * and false to entail the intended action. */
/* This is the same as a ^ b ^ c (chained XOR), 
 * which is used to count the parity of truth values. */
int a = adjustment.adjustmentAccount.isIncrease ? 1 : 0;
int b = adjustment.increaseVATLine ? 1 : 0;
int c = adjustment.vatItem.isSalesType ? 1 : 0;

if ((a + b + c) % 2 == 1)
{
    entry2.setDebit(adjustment.total);          // Odd number of trues
    entry2.setCredit(0d);
}
else
{
    entry2.setCredit(adjustment.total);         // Even number of trues
    entry2.setDebit(0d);
}
Run Code Online (Sandbox Code Playgroud)

  • 智能但非常难以理解的解决方案.这意味着难以编辑,维护和理解.我会避免编写那种"智能"代码. (12认同)
  • @XavierHo:(T ^ T)^ F = F ^ F = F.(F ^ F)^ T = F ^ T = T.(F ^ F)^ F = F ^ F = F.因此,事实上,实际的XOR和结果列完全相同.使用XOR可以得到正确的结果.作为旁注,在基础电气工程(和加密!)类中,您使用XOR门来计算字节的奇偶校验,这正是我们的解决方案所做的. (3认同)

Ton*_*lba 5

致马丁史密斯的评论,我将补充:

请记住,卡诺可以帮助您简化条件.

  • 电气工程师的解决方案!:-) (4认同)