Summary: 在一系列布尔表达式中,某个变量带有“控制标记”(control flag)的做用。以break语句或return语句取代控制标记。java
动机:编程
在一系列条件表达式中,你经常会看到用以判断什么时候中止条件检查的控制标记:编程语言
Set done to false函数
While not doneoop
If(condition)测试
Do something编码
Set done to truespa
Next step of loopcode
这样的控制标记带来的麻烦超过了它所带来的便利。人们之因此会使用这样的控制标记,由于结构化编程原则告诉他们:每一个子程序只能有一个入口和一个出口。我赞同“单一入口”原则(并且现代编程语言也强迫咱们这样作),可是“单一出口”原则会让你在代码中加入讨厌的控制标记,大大下降条件表达式的可读性。这就是编程语言提供break语句和continue语句的缘由:用它们跳出复杂的条件语句。去掉控制标记所产生的效果每每让你大吃一惊:条件语句真正的用途会清晰得多。it
作法:
对控制标记的处理,最显而易见的办法就是使用Java提供的break语句或continue语句。
1.找出让你跳出这段逻辑的控制标记值。
2.找出对标记变量赋值的语句,代以恰当的break语句或 continue语句。
3.每次替换后,编译并测试。
在未能提供break和continue语句的编程语言中,可使用下述办法。
1.运用Extract Method,将整段逻辑提炼到一个独立函数中。
2.找出让你跳出这段逻辑的控制标记值。
3.找出对标记变量赋值的语句,代以恰当的return语句。
4.每次替换后,编译并测试。
即便在支持break和continue语句的编程语言中,咱们也优先考虑上述第二方案。由于return语句能够很是清楚地表示:再也不执行该函数中的其余任何代码。若是还有这一类代码,你迟早须要将这段代码提炼出来。
请注意标记变量是否会影响这段逻辑的最后结果。若是有影响,使用break语句以后还得保留控制标记值。若是你已经将这段逻辑提炼成一个独立函数,也能够将控制标记值放在return语句中返回。
范例1: 以break 取代简单的控制标记
下列函数用来检查一系列人名之中是否包含两个可疑人物的名字(这两我的的名字硬编码与代码中):
void checkSecuurity(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; } } } }
这种状况下很容易找出控制标记:当变量found被赋予true时,搜索就结束。咱们能够逐一引入break语句,直到替换掉全部found变量语句:
void checkSecuurity(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 checkSecuurity(String[] people){ for(int i=0; i < people.length; i++){ if(people[i].equals("Don")){ sendAlert(); break; } if(people[i].equals("John")){ sendAlert(); break; } } }
范例2:以return 返回控制标记
本项重构的另外一种形式将使用return语句。为了阐述这种方法,咱们把前面的例子稍加修改,以控制标记记录搜索结果:
void checkSecuurity(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"; } } } 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(); return "John"; } } } return found; }
最后彻底去掉控制标记:
String foundMiscreant(String[] people){ 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(); return "John"; } } } return ""; }
即便不须要返回某值,也能够用return语句来取代控制标记。这时候你只须要一个空的return语句就好了。
固然,若是以此办法去处理带有反作用的函数,会有一些问题。因此咱们须要先以Separate Query from Modifier将函数反作用分离出去。