Remove Control Flag(移除控制标记)

本文介绍如何通过替换控制标记为break或return语句来提高代码可读性,并提供了具体的重构步骤及示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在一系列表达式中,某个变量带有控制标记的作用

以break语句或return语句取代控制标记

动机

在一系列条件表达式中,你常常会用到[用以何时停止条件检查]的控制标记。

set done to false
while not done
if (condition)
do something
set done to true
next step of loop

这样的控制标记带来的麻烦超过了它所带来的便利。人们之所以会使用这样的控制标记,因为结构化编程原则告诉它们,每个子程序只能有一个入口和出口。我赞同单一入口原则,但是单一出口原则会让你在代码中加入讨厌的控制标记,大大降低条件表达式的可读性,这就是编程语言提供break语句和continue语句的原因。你可以用它们跳出复杂的条件语句,去掉控制标记所产生的效果往往让你大吃一惊:条件语句的真正用途会清晰的多。

作法

1. 找出[让你得以跳出这段逻辑]的控制标记值。

2. 找出将可跳出条件之值赋予标记变量的那个语句,代以恰当的break语句或continue语句。

3. 每次替换后,编译并测试。

在没有break语句的语言中

1. 运用Extract Method,将整段逻辑提炼到一个独立函数中。

2. 找出那些[让你得以跳出这段逻辑]的控制标记值。

3.  找出将可跳出条件之值赋予标记变量的那个语句,代以恰当的return语句。

4. 每次替换后,编译并测试。

即使在支持break语句的语言中,也优先使用第二种。

如果这些控制标记对你还有作用,那你必须在break语句之后保留这些控制值,或者用提炼出来的函数的return语句把值返回。

以break取代简单的控制标记

下列函数中用来检查一系列人名中是否包含两个可疑人物的名字(这两个人的名字硬编码与代码中)

void checkSecurity(String[] people) {
boolean found = false;
for (int i = 0; i < people.length; i++) {
if (! found) {
if (people[i].equals ("Don")){
sendAlert();
found = true;
}
if (people[i].equals ("John")){
sendAlert();
found = true;
}
}
}
}

这种情况下,很容易找出控制标记,将变量被赋予true时,搜索就此结束。我可以逐一引入break语句。

void checkSecurity(String[] people) {
boolean found = false;
for (int i = 0; i < people.length; i++) {
if (! found) {
if (people[i].equals ("Don")){
sendAlert();
break;
}
if (people[i].equals ("John")){
sendAlert();
found = true;
}
}
}
}

最后获得这样的成果

void checkSecurity(String[] people) {
boolean found = false;
for (int i = 0; i < people.length; i++) {
if (! found) {
if (people[i].equals ("Don")){
sendAlert();
break;
}
if (people[i].equals ("John")){
sendAlert();
break;
}
}
}
}

然后我就可以把对控制标记的所有引用都去掉

void checkSecurity(String[] people) {
for (int i = 0; i < people.length; i++) {
if (people[i].equals ("Don")){
sendAlert();
break;
}
if (people[i].equals ("John")){
sendAlert();
break;
}
}
}

以return返回控制标记

本项重构的另一种形式将使用return语句,为了阐述这种用法,我把前面的例子稍加修改,以控制标记纪录搜索结果。

void checkSecurity(String[] people) {
String found = "";
200
for (int i = 0; i < people.length; i++) {
if (found.equals("")) {
if (people[i].equals ("Don")){
sendAlert();
found = "Don";
}
if (people[i].equals ("John")){
sendAlert();
found = "John";
}
}
}
someLaterCode(found);
}

在这里,变量found做了两件事,它既是控制标记,也是运算结果。遇到这种情况,我喜欢先把计算found变量的代码提炼到一个独立函数中

void checkSecurity(String[] people) {
String found = foundMiscreant(people);
someLaterCode(found);
}
String foundMiscreant(String[] people){
String found = "";
for (int i = 0; i < people.length; i++) {
if (found.equals("")) {
if (people[i].equals ("Don")){
sendAlert();
found = "Don";
}
if (people[i].equals ("John")){
sendAlert();
found = "John";
}
}
}
return found;
}

然后以return语句取代控制标记

String foundMiscreant(String[] people){
String found = "";
for (int i = 0; i < people.length; i++) {
if (found.equals("")) {
if (people[i].equals ("Don")){
sendAlert();
return "Don";
}
if (people[i].equals ("John")){
sendAlert();
found = "John";
}
}
}
return found;
}

最后完全去掉控制标记

String foundMiscreant(String[] people){
for (int i = 0; i < people.length; i++) {
if (people[i].equals ("Don")){
sendAlert();
return "Don";
}
if (people[i].equals ("John")){
sendAlert();
return "John";
}
}
return "";
}

即使不需要返回某值,你也可以使用return语句来取代控制标记,这时候你只需要一个空的return语句就可以了。

当然,如果以此办法去处理带有副作用的函数,会有一些问题。所以,我需要先以Separate Query from Modifier将函数副作用分离出去,稍后你会看到这方面的例子。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值