小酌重構系列[21]——避免雙重否認

避免雙重否認

在天然語言中,雙重否認表示確定。可是在程序中,雙重否認會下降代碼的可讀性,使程序不易理解,容易產生錯覺。
人一般是用「正向思惟」去理解一件事情的,使用雙重否認的判斷,須要開發者以「逆向思惟」的方式去理解它的含義。
另外,在寫程序時,"!"符號很容易被疏忽和遺漏,一不當心則會編寫出錯誤的代碼,從而產生bug。
因此,在程序中,咱們應當儘可能避免使用雙重否認。html

優惠券是否未被使用?

仍是以在線商城給用戶發放優惠券爲例,因爲優惠券的初始狀態是未被使用的,因此設計人員將優惠券的使用狀態設計爲IsUnused。設計

/// <summary>
/// 優惠券
/// </summary>
public class Coupon
{
    /// <summary>
    /// 是否未被使用
    /// </summary>
    public bool IsUnused { get; set; }
}


這樣設計會帶來兩個小問題code

  • IsUnused表示「優惠券是否未被使用」,這句話自己是比較拗口的,開發人員須要「逆向思惟」去理解它的含義。
  • 在寫程序時,若是要判斷「優惠券已經被使用」,則須要編寫比較繞彎的程序

 

// 若是優惠券已經被使用了
if (!coupon.IsUnused)
{
    // 業務邏輯
}

這段代碼若是沒有第1行的註釋,是比較難於理解的,也許你是用如下方式理解的。htm

SNAGHTML38b01d61

理解這段代碼看起來頗爲費勁,咱們應該換種方式來理解它。blog

image

所以,將屬性設計爲IsUsed更爲合適。ci

/// <summary>
/// 優惠券
/// </summary>
public class Coupon
{
    /// <summary>
    /// 是否被使用
    /// </summary>
    public bool IsUsed { get; set; }
}

編寫的判斷語句,可讀性良好,也易於理解。開發

// 若是優惠券已經被使用了
if (coupon.IsUsed)
{
    // 業務邏輯
}

PS:設計程序畢竟不是唱Rap,你不必把本身饒進去了,又把別人也繞進去,你們都能輕易讀懂的代碼纔多是好的代碼。get

示例

重構前

這段代碼使用!customer.IsNotFlagged判斷「客戶帳戶被標記」,若是沒有註釋,這個判斷就比較難理解。it

public class Order
{
    public void Checkout(IEnumerable<Product> products, Customer customer)
    {
        // 若是客戶帳戶被標記了
        if (!customer.IsNotFlagged)
        {
            // 記錄錯誤並返回
            return;
        }

        // 正常的訂單處理流程
    }
}

public class Customer
{
    public decimal Balance { get; private set; }

    public bool IsNotFlagged
    {
        get { return Balance < 30m; }
    }
}

程序本意是爲了表達一個確定的語義——「若是客戶帳戶是被標記的」,既然如此,咱們何不直接用確定的語義來表示它呢?class

重構後

重構後,代碼讀起來就更加直觀了,也很容易被理解。

public class Order
{
    public void Checkout(IEnumerable<Product> products, Customer customer)
    {
        // 若是客戶帳戶被標記了
        if (customer.IsFlagged)
        {
            // 記錄錯誤並返回
            return;
        }

        // 正常的訂單處理流程
    }
}

public class Customer
{
    public decimal Balance { get; private set; }

    public bool IsFlagged
    {
        get { return Balance >= 30m; }
    }
}

小結

在設計bool類型的屬性時,不只要表達清楚它所表示的業務含義,還應當考慮編寫代碼時的複雜性,儘可能避免使用雙重否認。

相關文章
相關標籤/搜索