记得去年 11 月份,刚入职的时候,领导把我分配到一个翻新老项目的项目组中。设计模式
当初,刚进入公司仍是蛮激动的,看到这个有点年纪的老项目,打开编辑器,看了看代码,我差点忍不住哭了。编辑器
内心暗想,“这是哪位离职的老前辈写的代码,这口锅我真不想背”,功能模块没有任何注释,业务逻辑从头至尾写下来的,没有代码规范,看着这一堆老代码,我无从下手。ide
这时背后一我的,拍了拍我肩膀,我一会儿缓过神来,原来是项目组的负责人。函数
鹿呀,咱们这个老项目,在此基础上,要增长一个功能,这个功能就交给你去作了,项目快到上线了,今天尽快完成吧。而后把大致功能和我说了一通。测试
没办法,只能硬着头皮去搞,我找到了那个功能页面的代码,正开始屡屡业务逻辑,下面一个代码结构让我眼前一亮。设计
1if(type == 'fn1'){ // 功能1 2 let a = 1; 3 let arr = []; 4 // 具体功能实现 5 // ... 6 7}else if(type == 'fn2'){ // 功能2 8 // 具体功能实现 9 // ... 10 11}else if(type == 'fn3'){ // 功能3 12 // 具体功能实现 13 // ... 14 15}else if(type == 'fn4'){ // 功能4 16 // 具体功能实现 17 // ... 18 19}else if(type == 'fn5'){ // 功能5 20 // 具体功能实现 21 // ... 22 23}else if(type == 'fn6'){ // 功能6 24 // 具体功能实现 25 // ... 26 27}else if(type == 'fn7'){ // 功能7 28 // 具体功能实现 29 // ... 30 31}else if(type == 'fn8'){ // 功能8 32 // 具体功能实现 33 // ... 34 35}else{ 36 // 具体功能实现 37 // ... 38}
哎呀个人妈呀,这一长串,看的我有点晕,这不是人们传说中的
if-else 调用侠客吗?调试
并且我又仔细看看了看每一个 else if 内部功能代码实现,基本每一个功能全部逻辑代码都堆砌在 else-if 中。代码规范
并且好像这些功能的实现并非一我的完成的,而是通过了好几轮前辈的接手,每当增长一个需求,该项目开发者就增长一个 else-if,因此才有了今天我所看到的结果。code
本来我也能够轻松增长个 else-if 就完成任务的,但我这我的有强迫症,不想再当一个 if-else 侠客了,好吧,开始写个人新功能。对象
写完以后的代码以下:
1function readNewFile(file){ 2 // 具体功能封装 3 // ... 4} 5 6const modelObj = { 7 fn1(file){ // 功能1 8 // ... 9 }, 10 fn2(file){ // 功能2 11 // ... 12 }, 13 fn3(file){ // 功能3 14 // ... 15 }, 16 readNewFile(file){ // 功能4 17 // 新增长的功能 18 // ... 19 }, 20 21 // 其余功能封装 22 // ... 23} 24 25function main(type, file){ 26 modelObj[type](file) 27}
写完以后,我把代码提交给个人负责人看,看完以后,没错,大家看完可能也会问,你这不是没事给本身找事干吗,明明能够增长一个 else-if 完事,你却额外增长了这么多代码?
没错,功能我实现了,代码多出了几乎一倍,反倒被要求从新改回原来的 else-if。鹿哥性格大家又不是不知道。我说,对不起,这是个人写代码习惯,正当我解释为何要这样写的时候,负责人说,行了,先这样吧。
虽然内心有一万句不爽,可是我仍是默默的转身离开了。
小结
这就是我刚刚实习的时候,碰到的第一件比较棘手的事情,我很理解负责人的心情,毕竟项目快速上线要紧,可是我认为给别人留条后路,就是给本身留条后路。
鹿哥,此话怎说,怎么感受你话里有话。并且你尚未说为何你要这么麻烦的去增长功能?
好吧,不卖关子了,其实这样的写法并非我本身发明的,而是设计模式中的策略模式,能够说是老前辈在几十年的项目中总结出来,至于为何这么写,确定是有它的道理的。
咱们先分析一下,上方原始代码的缺陷有哪些?
一、最明显的缺陷就是每一个 else-if 中的代码有一堆实现功能的逻辑。一旦 else-if 出现问题,整个 else-if 中的其余功能全都不能用了。
二、若是增长一个功能,须要无限的叠加 else-if。
这两个看起来并无什么毛病呀?别急,听我慢慢细说。
为何把每一个功能抽离成函数?由于像这种老项目,已经被不少前辈写过,项目很容易出现问题,一旦出现问题,很难定位代码,咱们更不可能找到离职的员工询问具体哪出错误了。
若是咱们单独抽离成函数,当该函数内部出现问题的时候,咱们经过断点调试,能够直接定位问题出如今哪里。而不像之前在if-else 海洋里探索定位问题。
并且每一个函数单独封装起来,由于遵循设计模式原则之一,单一功能原则。每一个函数只能干一件事,每一个功能都是独立分离的,这样尽最大可能实现功能函数之间的解耦。
有关第二点,为何会设置一个对象映射,而不是继续增长 else-if?
此次咱们增长一个功能,可能几年以后,客户需求有变,须要再增长一个功能,而增长功能的人换了,那么这个增长功能的人,没必要担忧原来的功能逻辑实现,只须要在这个对象中增长一个函数,在函数内部增长一个功能实现就 OK 了。
并且总体看起来,代码规范和总体的代码结构很是的清晰,不止于一旦出现问题,在修改过程当中致使其余地方出现问题,从而影响项目的开发进度。
作完以后,我直接把个人代码扔给了咱们公司的测试小姐姐,小姐姐对我笑了笑,咳咳,后来.....
可想而知,测试小姐姐在测试的时候,不用再把整个 else-if 拿过来测试了,而是直接拿我写的功能函数,只测试增长的功能就完成了。
回到最初那句话,给别人留条后路,就是给本身留条后路。我给测试小姐姐留了一条后路,后来就... (大家懂得)
最后
这件事情,让我产生深入的感悟。若是能用哲学中老子的“道”去阐述的话,将复杂的问题转化为最简单的哲学思想,而后直至事物的核心与本质。
老子同时将“道”称为“无”和“有”,“由于它没有形象,因此是“无”;由于它真实存在,因此是“有”。
那么实际开发项目中,项目最初的本质就是设计模式的运用,设计模式的核心思想就是「封装变化」。就是变与不变,变化的是扩展,不变的是稳定。变与不变又可相互转化。所谓有形化为无形,有法化为没法。
正所谓,道可道,很是道,名可名,很是名。玄之又玄,众妙之门也。