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


避免雙重否定

在自然語言中,雙重否定表示肯定。但是在程序中,雙重否定會降低代碼的可讀性,使程序不易理解,容易產生錯覺。
人通常是用“正向思維”去理解一件事情的,使用雙重否定的判斷,需要開發者以“逆向思維”的方式去理解它的含義。
另外,在寫程序時,"!"符號很容易被疏忽和遺漏,一不小心則會編寫出錯誤的代碼,從而產生bug。
所以,在程序中,我們應當盡量避免使用雙重否定。

優惠券是否未被使用?

還是以在線商城給用戶發放優惠券為例,由於優惠券的初始狀態是未被使用的,所以設計人員將優惠券的使用狀態設計為IsUnused。

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


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

  • IsUnused表示“優惠券是否未被使用”,這句話本身是比較拗口的,開發人員需要“逆向思維”去理解它的含義。
  • 在寫程序時,如果要判斷“優惠券已經被使用”,則需要編寫比較繞彎的程序

 

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

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

SNAGHTML38b01d61

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

image

因此,將屬性設計為IsUsed更為合適。

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

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

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

PS:設計程序畢竟不是唱Rap,你沒必要把自己饒進去了,又把別人也繞進去,大家都能輕易讀懂的代碼才可能是好的代碼。

示例

重構前

這段代碼使用!customer.IsNotFlagged判斷“客戶賬戶被標記”,如果沒有注釋,這個判斷就比較難理解。

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

程序本意是為了表達一個肯定的語義——“如果客戶賬戶是被標記的”,既然如此,我們何不直接用肯定的語義來表示它呢?

重構后

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

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類型的屬性時,不僅要表達清楚它所表示的業務含義,還應當考慮編寫代碼時的復雜性,盡量避免使用雙重否定。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM