Skip to content

《重构》10. 简化条件逻辑

🏷️ 《重构》

10.1 分解条件表达式(Decompose Conditional)

本手法其实只是提炼函数(Extract Function)的一个应用场景。

重构前

csharp
if (aDate >= plan.SummerStart && aDate <= plan.SummerEnd)
{
    charge = quantity * plan.SummerRate;
}
else
{
    charge = quantity * plan.RegularRate + plan.RegularServiceCharge;
}

重构后

csharp
if (IsSummer())
{
    charge = SummerCharge();
}
else
{
    charge = RegulargeCharge();
}

10.2 合并条件表达式(Consolidate Conditional Expression)

重构前

csharp
if (anEmployee.Seniority < 2) return 0;
if (anEmployee.MonthsDisabled > 12) return 0;
if (anEmployee.IsPartTime) return 0;

重构后

csharp
if (IsNotEligibleForDisability()) return 0;

bool IsNotEligibleForDisability()
{
    return anEmployee.Seniority < 2 || anEmployee.MonthsDisabled > 12 || anEmployee.IsPartTime;
}

10.3 以卫语句取代嵌套条件表达式(Replace Nested Conditional with Guard Clauses)

重构前

csharp
int result;

if (isDead)
{
    result = DeadAmount();
}
else
{
    if (isSeparated)
    {
        result = SeparatedAmount();
    }
    else
    {
        if (isRetired)
        {
            result = RediredAmount();
        }
        else
        {
            result = NormalAmount();
        }
    }
}

return result;

重构后

csharp
if (isDead) return DeadAmount();
if (isSeparated) return SeparatedAmount();
if (isRetired) return RediredAmount();
return NormalAmount();

10.4 以多态取代条件表达式(Replace Conditional with Polymorphism)

多态是面向对象编程的关键特性之一。

重构前

csharp
switch (bird.Type)
{
    case "EuropeanSwallow":
        return "average";
    case "AfricanSwallow":
        return bird.NumberOfCoconuts > 2 ? "tired" : "average";
    case "NorwegianBlueParrot":
        return bird.Voltage > 100 ? "scorched" : "beautiful";
    default:
        return "unknown";
}

重构后

csharp
private class Bird
{
    public string Type { get; internal set; }
    public int NumberOfCoconuts { get; internal set; }
    public int Voltage { get; internal set; }
    public virtual string Plumage => "unknown";
}

private class EuropeanSwallow : Bird
{
    public override string Plumage => "average";
}

private class AfricanSwallow : Bird
{
    public override string Plumage => NumberOfCoconuts > 2 ? "tired" : "average";
}

private class NorwegianBlueParrot : Bird
{
    public override string Plumage => Voltage > 100 ? "scorched" : "beautiful";
}

10.5 引入特例(Introduce Special Case)

曾用名引入 NULL 对象(Introduce Null Object)

重构前

csharp
if ("unknown".Equals(aCustomer)) customerName = "occupant";

重构后

csharp
class UnknownCustomer : Customer
{
    public override string Name => "occupant";
}

10.6 引入断言(Introduce Assertion)

C# 中貌似没法直接在处理中引入断言,只能通过测试类来实现类似功能。

下面的示例使用的是 JavaScript 语言,其中的断言 assert 方法是单独的插件提供的。

断言是一个条件表达式,应该总是为真。如果它失败,表示程序员犯了错误。断言的失败不应该被系统任何地方捕捉。

重构前

csharp
if (this.discountRate)
    base = base - (this.discountRate * base);

重构后

csharp
assert(this.discountRate >= 0);
if (this.discountRate)
    base = base - (this.discountRate * base);

附 1. 引用

  1. 《重构:改善既有代码的设计》 -- 马丁·福勒(Martin Fowler