掘金的小伙伴们,你们好,我是二哥呀!java
在某乎上看到一个接近万赞的高赞回答,一开始看的时候我嘴角是上扬的,还会笑出猪声,随后情绪就急转直下,莫名心酸!题目是这样的:程序员
先来看一下匿名做者的回答,没看过的同窗记得以泪洗面哈。编程
我曾经接手过一份代码,遇到过一个有 30 多个 if-else 嵌套 if-else 的模块。数组
内心骂骂咧咧,“谁他喵写的这玩意!”而后翻了一遍代码的 history。markdown
大体状况是这样的:第一个程序员写下这段代码时,只有 2 个 if-else;后来需求逐渐增长,先是 1 个、2 个,而后量变引发质变,因而逻辑分支快速扩张。oop
到这时候已经没有人愿意去重构 switch 或者设计模式了,毕竟复杂度摆在那里,万一崩了还得背锅。学习
大概三四个程序员接手这段代码后,就编程我如今这种局面了。测试
第一个程序员绝对没有料到那么简单的逻辑在以后会变得这么复杂,甚至在增长第一个第二个 if-else 时,也只是很随意的加上。优化
因此我以为,这锅绝对是甲方的,让他娘的随便改需求。这么一想内心就好受多了,编程嘛,最重要的是看得开!
因而我又追加了两条 if-else,而后测试、提交,下班。
看完了做者的回答,二哥强忍着无名的悲伤来讲两句。
十多年的编程生涯里,的确有过无数次的冲动,想要把原有的代码重构,想要调优,最后大多数都无疾而终,尤为是随着年龄的增加,反而愈来愈胆小怕事,有些真的是不敢乱动,只能忍痛让原有的代码更烂一些。
毕竟背锅是大事,嘿嘿。
有时候,不能把代码当作是艺术品,要可以适度忍受不完美,程序能跑起来,bug 数量可控,有啥问题能够解决也是很重要的。
若是重构了,出了问题,本身背锅是注定的,可能还会连累了测试小姐姐。
记得在外企的第二年,因为组里面有个新人的代码写得实在是太烂,我就忍不住前先后后优化了一遍,毕竟做为 Team Leader,要对新人负责,要为团队负责,结果你们猜怎么样?
我被领导臭骂了一顿!
缘由很简单,我特么引入了一个 Bug,Code Review 的时候尚未检查出来,测试也没有测试到,结果到了正式环境,刚巧碰到领导在日方出差,领导要给领导的领导展现成果,结果程序出了 bug,而后领导被狠狠地臭骂了一顿。
领导被批了,那天然一通越洋电话打过来,把我直接骂哭!
当时还年轻,那叫一个委屈啊。但能怎么办,本身的锅不背让谁背?
后来回洛阳后,团队规模变小,本身重构的欲望又涌上心头,毕竟此次没人能管得了我,看到谁写的代码烂,就直接一顿操做猛如虎,重构到本身心满意足为止。
即使是引入了新的 Bug 也不要紧,毕竟老板也不懂,好忽悠,嘿嘿。
老板虽然不懂代码,但懂得写代码哪能没有 Bug——通过个人不懈努力,成功给老板灌输了这个思想,要想不出 Bug,就增长测试团队的人手,领导可不肯意多发一份工资。
成功洗脑老板后,我真的有一段时间是飘到了极点,狠起来连本身的代码都重构,一遍又一遍,手头最常常看的两本书,一本《代码的整洁之道》,一本《重构·改善既有代码的设计》。
从简单的变量命名、方法命名,到缩减方法的行数,能拆分就拆分,尽可能保证每一个方法的行数不超过一个小拇指那么长。为了适配设计模式,我当时还买了一本《设计模式之禅》,真的是殚精竭虑。
如今想一想那段日子真疯狂,有时候为了修本身重构后带来的新 Bug,真的是熬了很多夜。
但有一说一,那段日子的进步也是肉眼可见的。
不过,话又说回来,对稳定性要求比较高的项目,若是能力没到那份上,仍是尽可能少重构,搞很差版本更新的日志里就会写下一条:XXX 程序员被祭天了!
最好是等到领导忍不住下了死命令,限尔等多少天以内,务必把这座屎山给搬走!到了那时候,再大展拳脚也不迟。
若是真的是安耐不住,一肚子的重构、调优想法没法获得施展,我给你们推荐一个好办法,就是本身搞一个练手项目,能够是本身开发的,也能够是 GitHub 上成熟的项目,好比说我一直推荐的 vhr、mall、miaosha 等等,把源码 fork 下而后拉下来,在本地跑一跑,尝试去读一读源码,以为哪里须要重构了,就动手实践一遍,即使是出错了,也谁都影响不到,对吧?
有些同窗若是以为本身比较厉害的话,能够去拿那些顶级的第三方类库作实验,重构完必定要记得测试,而且在提交 PR 的时候附带上本身的测试报告,若是项目的做者认为你重构的有水平,没准你一跃就成为了项目的维护者,简历上也是加分项。
但对于公司的那堆屎山,动刀子的时候尽可能猥琐点,省得把本身埋了。
再说回知乎上关于 if-else 和 switch 这个题目。朋友 @yes 在回答里提到过 Dubbo 源码中的 ChannelEventRunnable 类的 run()
方法,我用 Sourcegraph 插件看了一下 GitHub 上 Dubbo 的源码,还真的是挺有学习价值的。
public void run() {
if (state == ChannelState.RECEIVED) {
try {
handler.received(channel, message);
} catch (Exception e) { }
} else {
switch (state) {
case CONNECTED:
try {
handler.connected(channel);
} catch (Exception e) {}
break;
case DISCONNECTED:
try {
handler.disconnected(channel);
} catch (Exception e) {}
break;
case SENT:
try {
handler.sent(channel, message);
} catch (Exception e) { }
break;
case CAUGHT:
try {
handler.caught(channel, exception);
} catch (Exception e) { }
break;
default:
}
}
}
复制代码
看到没,这段代码里先用 if 作了判断,而后才在 else 中使用 switch 作了分支判断。为何不所有使用 switch 呢?
官方还特地给了个说明。
我把其中关键的一点摘录出来,你们看一下就明白了。
现代 CPU 都支持分支预测(branch prediction)和指令流水线(instruction pipeline),这两个结合能够极大提升 CPU 效率。对于像简单的 if 跳转,CPU 是能够比较好地作分支预测的。可是对于 switch 跳转,CPU 则没有太多的办法。switch 本质上是根据索引,从地址数组里取地址再跳转的。
因此说,不是全部状况下,把 if-else 重构成 switch 就是最好的选择,仍是要因地制宜。又学到了新的知识,哈哈。
多说一句哈,若是真的想重构代码,建议学一学设计模式,持续霸榜 GitHubTrending。设计模式是软件设计中常见问题的典型解决方案,它们就像能根据需求进行调整的预制蓝图, 可用于解决代码中反复出现的设计问题,若是不懂设计模式的话,遇到这些问题就只能抓瞎了。
最后,但愿你们在重构 if-else 的时候想想,除了 switch,还有没有其余更好的选择,也许 Dubbo 的源码就给出了方案。
我是二哥呀,下期见,记得点赞哟~~~~