在天然语言中,双重否认表示确定。可是在程序中,双重否认会下降代码的可读性,使程序不易理解,容易产生错觉。
人一般是用“正向思惟”去理解一件事情的,使用双重否认的判断,须要开发者以“逆向思惟”的方式去理解它的含义。
另外,在写程序时,"!"符号很容易被疏忽和遗漏,一不当心则会编写出错误的代码,从而产生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类型的属性时,不只要表达清楚它所表示的业务含义,还应当考虑编写代码时的复杂性,尽可能避免使用双重否认。