在天然語言中,雙重否認表示確定。可是在程序中,雙重否認會下降代碼的可讀性,使程序不易理解,容易產生錯覺。
人一般是用「正向思惟」去理解一件事情的,使用雙重否認的判斷,須要開發者以「逆向思惟」的方式去理解它的含義。
另外,在寫程序時,"!"符號很容易被疏忽和遺漏,一不當心則會編寫出錯誤的代碼,從而產生bug。
因此,在程序中,咱們應當儘可能避免使用雙重否認。html
仍是以在線商城給用戶發放優惠券爲例,因爲優惠券的初始狀態是未被使用的,因此設計人員將優惠券的使用狀態設計爲IsUnused。設計
/// <summary> /// 優惠券 /// </summary> public class Coupon { /// <summary> /// 是否未被使用 /// </summary> public bool IsUnused { get; set; } }
這樣設計會帶來兩個小問題code
// 若是優惠券已經被使用了 if (!coupon.IsUnused) { // 業務邏輯 }
這段代碼若是沒有第1行的註釋,是比較難於理解的,也許你是用如下方式理解的。htm
理解這段代碼看起來頗爲費勁,咱們應該換種方式來理解它。blog
所以,將屬性設計爲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類型的屬性時,不只要表達清楚它所表示的業務含義,還應當考慮編寫代碼時的複雜性,儘可能避免使用雙重否認。