- 使用 Spring Initializr 创建 Spring Boot 应用程序
- 在Spring Boot中配置Cassandra
- 在 Spring Boot 上配置 Tomcat 连接池
- 将Camel消息路由到嵌入WildFly的Artemis上
本文分享自华为云社区《以卫语句取代嵌套条件表达式 (Replace Nested Conditional with Guard Clauses)》,作者:JavaEdge。
条件表达式通常有两种风格:
这两类条件表达式有不同用途,这一点应该通过代码表现出来:
这样的单独检查常常被称为“卫语句”(guard clauses)
以卫语句取代嵌套条件表达式的精髓就是:给某一条分支以特别的重视。如果使用if-then-else结构,你对if分支和else分支的重视是同等的。这样的代码结构传递给阅读者的消息就是:各个分支有同样的重要性。而卫语句是在告诉读者:“这种情况不是本函数的核心逻辑所关心的,如果它真发生了,请做一些必要的整理工作,然后退出。”
“每个函数只能有一个入口和一个出口”的观念根深蒂固于某些程序员。当我处理他们编写的代码时,经常需要使用以卫语句取代嵌套条件表达式。现今编程语言都会强制保证每个函数只有一个入口,至于“单一出口”规则,其实不那么有用。保持代码清晰才是最关键的:若单一出口能使这个函数更清楚易读,那就使用单一出口;否则不必。
选中最外层需要被替换的条件逻辑,将其替换为卫语句。
测试。
有需要的话,重复上述步骤。
如果所有卫语句都引发同样的结果,可以使用【合并条件表达式】合并之。
计算要支付给员工的工资。只有还在公司上班的员工才需要支付工资,所以这个函
数需要检查两种“员工已经不在公司上班”的情况。
public Long payAmount(Employee employee) {
long result;
if (employee.isSeparated) {
result = 0;
} else {
if (employee.isRetired) {
result = 0;
} else {
// logic to compute amount
lorem.ipsum(dolor.sitAmet);
consectetur(adipiscing).elit();
sed.do.eiusmod = tempor.incididunt.ut(labore) && dolore(magna.aliqua);
ut.enim.ad(minim.veniam);
result = someFinalComputation();
}
} return result;
}
嵌套的条件逻辑让我们看不清代码真实的含义。只有当前两个条件表达式都不为真的时候,这段代码才真正开始它的主要工作。所以,卫语句能让代码更清晰地阐述自己的意图。一如既往地,我喜欢小步前进,所以我先处理最顶上的条件逻辑。
public Long payAmount(Employee employee) {
long result;
if (employee.isSeparated) {
result = 0;
}
if (employee.isRetired) {
result = 0;
} else { // logic to compute amount
lorem.ipsum(dolor.sitAmet);
consectetur(adipiscing).elit();
sed.do.eiusmod = tempor.incididunt.ut(labore) && dolore(magna.aliqua);
ut.enim.ad(minim.veniam);
result = someFinalComputation();
} return result;
}
做完这步修改,我执行测试,然后继续下一步。
public Long payAmount(Employee employee) {
long result;
if (employee.isSeparated) {
return 0l;
}
if (employee.isRetired) {
return 0l;
}
lorem.ipsum(dolor.sitAmet);
consectetur(adipiscing).elit();
sed. do.eiusmod = tempor.incididunt.ut(labore) && dolore(magna.aliqua);
ut.enim.ad(minim.veniam);
result = someFinalComputation();
return result;
}
此时,result变量已经没有用处了,所以我把它删掉:
public Long payAmount(Employee employee) {
if (employee.isSeparated) {
return 0l;
}
if (employee.isRetired) {
return 0l;
}
lorem.ipsum(dolor.sitAmet);
consectetur(adipiscing).elit();
sed. do.eiusmod = tempor.incididunt.ut(labore) && dolore(magna.aliqua);
ut.enim.ad(minim.veniam);
return someFinalComputation();
}
能减少一个可变变量总是好的。
我们常常可以将条件表达式反转,从而实现以卫语句取代嵌套条件表达式。
public int adjustedCapital(Instrument anInstrument) {
int result = 0;
if (anInstrument.capital > 0) {
if (anInstrument.interestRate > 0 && anInstrument.duration > 0) {
result = (anInstrument.income / anInstrument.duration) * anInstrument.adjustmentFactor;
}
}
return result;
}
逐一替换。但这次在插入卫语句时, 我需要将相应的条件反转过来:
public int adjustedCapital(Instrument anInstrument) {
int result = 0;
if (anInstrument.capital <= 0) {
return result;
}
if (anInstrument.interestRate > 0 && anInstrument.duration > 0) {
result = (anInstrument.income / anInstrument.duration) * anInstrument.adjustmentFactor;
}
return result;
}
下一个条件稍微复杂一点,所以我分两步进行反转。首先加入一个逻辑非操作:
public int adjustedCapital(Instrument anInstrument) {
int result = 0;
if (anInstrument.capital <= 0) {
return result;
}
if (!(anInstrument.interestRate > 0 && anInstrument.duration > 0)) {
return result;
}
result = (anInstrument.income / anInstrument.duration) * anInstrument.adjustmentFactor;
return result;
}
但是在这样的条件表达式中留下一个逻辑非,会把我的脑袋拧成一团乱麻,所以我把它简化成:
public int adjustedCapital(Instrument anInstrument) {
int result = 0;
if (anInstrument.capital <= 0) {
return result;
}
if (anInstrument.interestRate <= 0 || anInstrument.duration <= 0) {
return result;
}
result = (anInstrument.income / anInstrument.duration) * anInstrument.adjustmentFactor;
return result;
}
这两行逻辑语句引发的结果一样,所以我可以用【合并条件表达式】将其合并:
public int adjustedCapital(Instrument anInstrument) {
int result = 0;
if (anInstrument.capital <= 0 || anInstrument.interestRate <= 0 || anInstrument.duration <= 0) {
return result;
}
result = (anInstrument.income / anInstrument.duration) * anInstrument.adjustmentFactor;
return result;
}
此时result变量做了两件事:一开始我把它设为0,代表卫语句被触发时的返回值;然后又用最终计算的结果给它赋值。我可以彻底移除这个变量,避免用一个变量承担两重责任,而且又减少了一个可变变量。
public int adjustedCapital(Instrument anInstrument) {
if (anInstrument.capital <= 0 || anInstrument.interestRate <= 0 || anInstrument.duration <= 0) {
return 0;
}
return (anInstrument.income / anInstrument.duration) * anInstrument.adjustmentFactor;
}
参考
我有一个包含几行的 HTML 表格。 我最初为其中一些表格行 (TR) 提供了一个 ID,然后我将使用 javascript 通过一些新的动态内容来设置其中一些表格行的 INNERHTML。 但是,I
在以下(Clojure)SO问题中:my own interpose function as an exercise 接受的答案是这样的: Replace your recursive call wi
我目前正在使用 Delphi7 和 ASTA 来处理客户端服务器与 Advantage DB 的通信。 我正在转向 Rad Studio XE Enterprise,并希望切换到不同但相似的解决方案,
当我尝试更新软件包时,我总是收到这条消息,我通常只是继续进行,一切都会正常进行。但我担心我不小心创建了一个比我想要的复杂得多的 Anaconda 环境。此线程 ( What does "the fol
这个问题在这里已经有了答案: 关闭 13 年前。 Possible Duplicate: Why not use tables for layout in HTML? 我知道现在每个人都在关注 DI
作为一名 Java 后端开发,日常工作中免不了要生成数据库表对应的持久化对象 PO,操作数据库的接口 DAO,以及 CRUD 的 XML,也就是 mapper。 Mybatis Generator 是
我需要用 bitshift 替换 Java 中的 Math.pow。 for (int i = n - 1; i >= 0; i--) Math.pow(16, n - i - 1) 其中 n
我对 Oracle 还很陌生。 可以肯定地说LTRIM(RTRIM())完全可以被 TRIM() 取代如果我想替换 Oracle 11g 中的前导和尾随空格? 此外,当我尝试在使用 JPA 的查询中使
此应用程序包含activity_main.xml、mainactivit.java 和一个Fragment 类。activity_main.xml 在RelativeLayout 中有一个Button
我正在研究将 Weblogic 10.x 替换为用于开发机器的 Apache Tomcat,我非常感谢任何人可能有的任何见解或建议。 任何试图在生产 webapp 服务器怪物上进行开发工作的人可能都知
我有以下 JS 代码,我想用 $ 符号替换所有 ₪ (₪)。 $(this).html($(this).html().replace(/₪/g,'$')); 但是它没有做任何事情。我还尝试
执行此操作的正确方法是什么?我有一个 标签,我想显示 那是内联的。 最佳答案 display: inline 应该可以解决问题。它将使 表现得像任何内联元素。 关于html - CSS:取代 h1 换
我有一个问题 - 当我改变方向时,我的第二个 fragment (此时处于 Activity 状态)被第一个 fragment 取代。我从来没有这样的行为,如果能解决它怎么办? 主要 Activity
我有多个结构,其格式与传递给 encodeParams 函数的 MapParameters 相同。不幸的是,对这些结构使用该函数会产生不需要的编码,包括嵌入的结构名称。无论如何,我可以使用 refle
前言 打开Android架构组件页面,我们可以发现一些最新发布的jetpack组件,如Room,DataStore, Paging3,DataBinding 等都支持了Flow。Google开
我正在尝试不区分大小写的模式匹配。为了学习,我尝试了以下方法,发现很难分析正在发生的事情。 String x = "Hello"; String pattern = "(?i)";
这个问题在这里已经有了答案: Why aren't my absolutely/fixed-positioned elements located where I expect? (3 个答案)
我有以下形式的 HTML 布局 .. .. // content .. 两个 header 都是 position: fixed 并设置为 header 1 刚好在 header 2 上方。这两个 h
阅读中this c++17 最终特性的总结我对结构化绑定(bind)的部分感到有点惊讶(强调我的): structured bindings Until now, there was a known
我正在集成一个用早期 Swift 编写的库。由于该库与 Swift 4 的兼容版本不可用,我正在自己删除错误。 有这一行: let pathBounds = CGPathGetBoundingBox(
我是一名优秀的程序员,十分优秀!