重构条件-Replace Nested Conditional with Guard Clauses以卫语句取代嵌套条件式五
创始人
2025-06-01 11:56:02
0

重构条件-Replace Nested Conditional with Guard Clauses以卫语句取代嵌套条件式五

1.以卫语句取代嵌套条件式

1.1.使用场景

函数中的条件逻辑使人难以看清正常的执行路径。使用卫语句表现所有特殊情况

根据我的经验,条件式通常有两种呈现形式。第一种形式是:所有分支都属于正常行为。第二种形式则是:条件式提供的答案中只有一种是正常行为,其他都是不常见的情况。
这两类条件式有不同的用途,这一点应该通过代码表现出来。如果两条分支都是正常行为,就应该使用形如「if…then…」的条件式;如果某个条件极其罕见,就应该单独检查该条件,并在该条件为真时立刻从函数中返回。这样的单独检查常常被称为卫语句(guard clauses)

Replace Nested Conditional with Guard Clauses 的精髓就是:给某一条分支以特别的重视。如果使用if-then-else 结构,你对if 分支和else 分支的重视是同等的。 这样的代码结构传递给阅读者的消息就是:各个分支有同样的重要性。

卫语句(guard clauses)就不同了,它告诉阅读者:『这种情况很罕见,如果它真的发生了,请做 一些必要的整理工作,然后退出。

1.2.如何做

  • 对于每个检查,放进一个卫语句。
  • 卫语句要不就从函数中返回,要不就抛出一个异常。
  • 每次将条件检查替换成卫语句后,编译并测试。
  • 如果所有卫语句都导致相同结果,请使用Consolidate Conditional Expressions (240)。

1.3.示例

想像一个薪资系统,其中以特殊规则处理死亡员工、驻外员工、退休员工的薪资。这些情况不常有,但的确偶而会出现。假设我在这个系统中看到下列代码

 double getPayAmount() {double result;if (_isDead) result = deadAmount();else {if (_isSeparated) result = separatedAmount();else {if (_isRetired) result = retiredAmount();else result = normalPayAmount();};}return result;};

在这段代码中,非正常情况的检查掩盖了正常情况的检查,所以我应该使用『卫语句」来取代这些检查,以提高程序清晰度。我可以逐一引入卫语句。让我们从最上面的条件检查动作开始:

 double getPayAmount() {double result;if (_isDead) return deadAmount();if (_isSeparated) result = separatedAmount();else {if (_isRetired) result = retiredAmount();else result = normalPayAmount();};return result;};

然后,继续下去,仍然一次替换一个检查动作:

 double getPayAmount() {double result;if (_isDead) return deadAmount();if (_isSeparated) return separatedAmount();if (_isRetired) result = retiredAmount();else result = normalPayAmount();return result;};

然后是最后一个:

 double getPayAmount() {double result;if (_isDead) return deadAmount();if (_isSeparated) return separatedAmount();if (_isRetired) return retiredAmount();result = normalPayAmount();return result;};

此时,result 变量已经没有价值了,所以我把它删掉

 double getPayAmount() {if (_isDead) return deadAmount();if (_isSeparated) return separatedAmount();if (_isRetired) return retiredAmount();return normalPayAmount();};

将条件反转

  public double getAdjustedCapital() {double result = 0.0;if (_capital > 0.0) {if (_intRate > 0.0 && _duration > 0.0) {result = (_income / _duration) * ADJ_FACTOR;}}return result;}

同样地,我逐一进行替换。不过这次在插入卫语句(guard clauses)时,我需要将相应的条件反过来:

   public double getAdjustedCapital() {double result = 0.0;if (_capital <= 0.0) return result;if (_intRate > 0.0 && _duration > 0.0) {result = (_income / _duration) * ADJ_FACTOR;}return result;}

下一个条件稍微复杂一点,所以我分两步进行逆反。首先加入一个逻辑非操作

  public double getAdjustedCapital() {double result = 0.0;if (_capital <= 0.0) return result;if (!(_intRate > 0.0 && _duration > 0.0)) return result;result = (_income / _duration) * ADJ_FACTOR;return result;}

但是在这样的条件表达式中留下一个逻辑非,会把我的脑袋拧成一团乱麻,所以我把它简化成下面这样

  public double getAdjustedCapital() {double result = 0.0;if (_capital <= 0.0) return result;if (_intRate <= 0.0 || _duration <= 0.0) return result;result = (_income / _duration) * ADJ_FACTOR;return result;}

这时候,我比较喜欢在卫语句内返回一个明确值,因为这样我可以一目了然地看到卫语句返回的失败结果。此外,这种时候我也会考虑使用Replace Magic Number with Symbolic Constant (204)。

  public double getAdjustedCapital() {double result = 0.0;if (_capital <= 0.0) return 0.0;if (_intRate <= 0.0 || _duration <= 0.0) return 0.0;result = (_income / _duration) * ADJ_FACTOR;return result;}

完成替换之后,我同样可以将临时变量移除

  public double getAdjustedCapital() {if (_capital <= 0.0) return 0.0;if (_intRate <= 0.0 || _duration <= 0.0) return 0.0;return (_income / _duration) * ADJ_FACTOR;}

相关内容

热门资讯

【MySQL】锁 锁 文章目录锁全局锁表级锁表锁元数据锁(MDL)意向锁AUTO-INC锁...
【内网安全】 隧道搭建穿透上线... 文章目录内网穿透-Ngrok-入门-上线1、服务端配置:2、客户端连接服务端ÿ...
GCN的几种模型复现笔记 引言 本篇笔记紧接上文,主要是上一篇看写了快2w字,再去接入代码感觉有点...
数据分页展示逻辑 import java.util.Arrays;import java.util.List;impo...
Redis为什么选择单线程?R... 目录专栏导读一、Redis版本迭代二、Redis4.0之前为什么一直采用单线程?三、R...
【已解决】ERROR: Cou... 正确指令: pip install pyyaml
关于测试,我发现了哪些新大陆 关于测试 平常也只是听说过一些关于测试的术语,但并没有使用过测试工具。偶然看到编程老师...
Lock 接口解读 前置知识点Synchronized synchronized 是 Java 中的关键字,...
Win7 专业版安装中文包、汉... 参考资料:http://www.metsky.com/archives/350.htm...
3 ROS1通讯编程提高(1) 3 ROS1通讯编程提高3.1 使用VS Code编译ROS13.1.1 VS Code的安装和配置...
大模型未来趋势 大模型是人工智能领域的重要发展趋势之一,未来有着广阔的应用前景和发展空间。以下是大模型未来的趋势和展...
python实战应用讲解-【n... 目录 如何在Python中计算残余的平方和 方法1:使用其Base公式 方法2:使用statsmod...
学习u-boot 需要了解的m... 一、常用函数 1. origin 函数 origin 函数的返回值就是变量来源。使用格式如下...
常用python爬虫库介绍与简... 通用 urllib -网络库(stdlib)。 requests -网络库。 grab – 网络库&...
药品批准文号查询|药融云-中国... 药品批文是国家食品药品监督管理局(NMPA)对药品的审评和批准的证明文件...
【2023-03-22】SRS... 【2023-03-22】SRS推流搭配FFmpeg实现目标检测 说明: 外侧测试使用SRS播放器测...
有限元三角形单元的等效节点力 文章目录前言一、重新复习一下有限元三角形单元的理论1、三角形单元的形函数(Nÿ...
初级算法-哈希表 主要记录算法和数据结构学习笔记,新的一年更上一层楼! 初级算法-哈希表...
进程间通信【Linux】 1. 进程间通信 1.1 什么是进程间通信 在 Linux 系统中,进程间通信...
【Docker】P3 Dock... Docker数据卷、宿主机与挂载数据卷的概念及作用挂载宿主机配置数据卷挂载操作示例一个容器挂载多个目...