switch case和if – else if - else的坏处
要想写出超长方法,就写一个switch-case,如果觉得不够长,就再写一个。
本人亲自重构过的有记录的最长的一个方法包含502个switch-case,加上每个case中一行实际工作代码,外加一些函数声明等,最终高达1030行。值得提一下的是重构后这个方法只有1行实际工作代码。实际上整个2000多行的模块重构后一共也只有180行。
注:此次重构已经录制为教学视频,地址:https://edu.csdn.net/course/detail/7269
两者带来的问题包括:
1. 单个方法冗长
2. 难以扩展
3. 难以维护
第一个问题是易于理解的,下面解释一下后面两个问题。
很多人都会说:“要想修改一个分支,或者添加一个分支,只要查找替换就可以了,没什么难度。”其实却不然。比如在代码中不同的位置,可能存在下例中的两处代码,都对同一类分支进行不同的处理。比如地图软件中存在河流,道路,边界,山峰,城市——又分为首都,省会……等等标志,这些标志的赋值、绘制、显示图例、选中时高亮等都需要用相似的分支处理不同(其中一些或许又相同)的行为。
switch (type) {
case 1: …;
case 2: …;
…
default: …;
}
if (type == 1) {
…;}
else if (type == 2) {
…;}
else {
}
看似只要全文搜索switch(type)和if (type ==)就能找到所有需要修改的地方,其实不然。比如以下这些情况:
- 如果type在某些地方局部变量名是itemType
- 如果type在某处是通过方法Type()访问的
- 如果Type在某处是通过get属性Type访问的
- 如果type是类的属性,有些地方写的是type,而另外一些地方是this.type
- 如果有些==在某些地方是type.equals()
- 如果某些地方type==1是type == 1(两个等号前后各有一个空格)
- 如果有些地方是switch( type)(type前面有一个空格)
- 如果某些地方是1==type(这甚至是一种推荐的用法)
- 如果有些地方type==n实际上在else(或default)中实现的
- ……
实际上,居然没有一种简单的方法来解决这个问题。在类的规模很大的时候(当一个方法可以达到1030行时,类的规模可想而知),或者类的封装不很充分的时候(比如type可以以某种形式外部访问),或者有多个人在维护一个不熟悉的类时,这种情况会变得非常危险。
每次终于找到Bug根源时,经常听到一句话:“谁能想到……”这就是地球上扔上70亿只黑猩猩时发生的问题。
面向对象的高内聚、低耦合原则就是要解决这种人类思维不可能解决的问题的,但是陈旧语法的存在却替代性地阻碍了面向对象的实施。