| 2021-03-09
嵌套过深的代码对可读性有害,而且容易出错。
而通过卫语句
来检查某一条件,如果不满足就直接快速失败。
卫语句
将计算逻辑与错误逻辑分离。通过消除错误检查和错误处理之间的认知距离,它释放了工程师的心算负担。
请在下面两个版本的代码中试着找一找bug:
response = server.Call(request)
if response.GetStatus() == RPC.OK:
if response.GetAuthorizedUser():
if response.GetEnc() == 'utf-8':
if response.GetRows():
vals = [ParseRow(r) for r in response.GetRows()]
avg = sum(vals) / len(vals)
return avg, vals
else:
raise EmptyError()
else:
raise AuthError('unauthorized')
else:
raise ValueError('wrong encoding')
else:
raise RpcError(response.GetStatus())
response = server.Call(request)
if response.GetStatus() != RPC.OK:
raise RpcError(response.GetStatus())
if not response.GetAuthorizedUser():
raise ValueError('wrong encoding')
if response.GetEnc() != 'utf-8':
raise AuthError('unauthorized')
if not response.GetRows():
raise EmptyError()
vals = [ParseRow(r) for r in response.GetRows()]
avg = sum(vals) / len(vals)
return avg, vals
答案:
wrong encoding
和 unauthorized
这两个错误信息写反了。
上面展示的重构技术就是 “卫语句” 。所以,**重构后的版本更容易读懂,也更容易维护。**重构以后,这个 bug 更容易被发现,因为,在代码中直接进行检查,检查后马上就处理错误信息。
下面是一些减少嵌套代码的原则:
- 尽量让条件语句块短小。将内容限制在局部,有利于增加可读性。
- 当循环或分支超过两层深度时,就要考虑重构它了。
- 可以将嵌套逻辑抽取到另一个函数中。假如你需要从一个列表中取出每一个元素,而每个元素又都是一个列表(例如,一个协议缓冲区中还有重复的字段),你就可以定义一个函数来处理每个对象,而不是使用双嵌套循环。
减少嵌套会使代码更易读,从而更容易发现可能存在的错误,更快的开发迭代,以及更高的稳定性。只要允许,就进行简化!
发表时间:June 05, 2017
原文作者:Elliott Karpilovsky