意大利XP倡导者Francesco Cirillo为他著名的“反对if行动 ”创建了一个网站,一时吸引了不少支持者 。Francesco认为 :
if所带来的问题主要在于建立了模块(方法、对象、组件等)之间的依赖,也增加了代码路径的分支(这会降低代码的可读性)。
Francesco举了一个示例,认为如下的代码:
// Bond class
double calculateValue() {
if(_type == BTP) {
return calculateBTPValue();
} else if(_type == BOT) {
return calculateBOTValue();
} else {
return calculateEUBValue();
}
}
应该使用多态将显式的if或switch语句消除:
// Bond class
double calculateValue() {
_bondProfile.calculate();
}
// AbstractBondProfile class
abstract double calculate();
// classe BTPBondProfile >> AbstractBondProfile
double calculate() {
...
}
// classe BOTBondProfile >> AbstractBondProfile
double calculate() {
...
}
// classe EUBondProfile >> AbstractBondProfile
double calculate() {
...
}
Francesco认为这样做的好处在于
当我们需要增加新的bond类型时,只需创建一个新的类型来保存这部分独立逻辑即可。
创建抽象类或接口并非是改进的唯一方式,我们的目的是将程序变得更灵活、更易于交流、更容易测试、并且随时拥抱变化。
对于“反对if行动”,Matteo Vaccari补充了几点做法 :
修改前 | 修改后 | |
---|---|---|
直接使用布尔运算结果 | if (foo) { | return (foo && bar || baz); |
使用辅助函数 | if (x > y) | return max(x, y); |
灵活使用0的作用 | int arraySum(int[] array) { | int arraySum(int[] array) { |
不过社区中对此也有不同看法 ,有人讽刺道:
哦,这里我发现了一个问题。尊敬的客户,您前一个顾问使用了“if”语句,让我把这个函数替换为80个新类,这样显得更加敏捷一些。
Don't Repeat Yourself看上去更敏捷一些。更好的做法是:等到出现第3遍重复代码的时候才去重构(不过也别等太久了)。这样可以避免很多无所谓的代码,也可以让程序员有更灵活的选择余地。
也有人为“反对if行动”进行了补充:
我想这个行动并不是说“删除所有的if代码”,而是将类型判断逻辑使用多态进行替换。如果把它称为“反对类型字段行动”会更合适一些。
“反对if行动”也在征集“if-free”的代码示例,您也可以在那里提交代码片断 。事实上,国内社区也提出了不少消除繁琐if语句的案例,如:
- Jeffrey Zhao编写了一个简单的类库 ,使.NET中的枚举类型可以携带一些信息,以便统一地获取数据或进行运算。
- 木野狐使用了State模式 ,简化了不同状态下,Web界面中相应组件的样式切换方式。
- Tristan G设计了一组流畅的API ,使开发人员能够方便地编写实体验证规则。
您在这方面是否也有独特的经验呢?不妨也一起分享出来吧。