记得去年 11 月份,刚入职的时候,领导把我分配到一个翻新老项目的项目组中。

当初,刚进入公司还是蛮激动的,看到这个有点年纪的老项目,打开编辑器,看了看代码,我差点忍不住哭了。

心里暗想,“这是哪位离职的老前辈写的代码,这口锅我真不想背”,功能模块没有任何注释,业务逻辑从头到尾写下来的,没有代码规范,看着这一堆老代码,我无从下手。

这时背后一个人,拍了拍我肩膀,我一下子缓过神来,原来是项目组的负责人。

鹿呀,我们这个老项目,在此基础上,要增加一个功能,这个功能就交给你去做了,项目快到上线了,今天尽快完成吧。然后把大体功能和我说了一通。

没办法,只能硬着头皮去搞,我找到了那个功能页面的代码,正开始屡屡业务逻辑,下面一个代码结构让我眼前一亮。

 1if(type == 'fn1'){  // 功能1 2  let a = 1; 3  let arr = []; 4  // 具体功能实现 5  // ... 6 7}else if(type == 'fn2'){ // 功能2 8  // 具体功能实现 9  // ...1011}else if(type == 'fn3'){ // 功能312  // 具体功能实现13  // ...1415}else if(type == 'fn4'){ // 功能416  // 具体功能实现17  // ...1819}else if(type == 'fn5'){  // 功能520  // 具体功能实现21  // ...2223}else if(type == 'fn6'){ // 功能624  // 具体功能实现25  // ...2627}else if(type == 'fn7'){  // 功能728  // 具体功能实现29  // ...3031}else if(type == 'fn8'){ // 功能832  // 具体功能实现33  // ...3435}else{36  // 具体功能实现37  // ...38}

哎呀我的妈呀,这一长串,看的我有点晕,这不是人们传说中的
if-else 调用侠客吗?

而且我又仔细看看了看每个 else if 内部功能代码实现,基本每个功能所有逻辑代码都堆砌在 else-if 中。

而且好像这些功能的实现并不是一个人完成的,而是经过了好几轮前辈的接手,每当增加一个需求,该项目开发者就增加一个 else-if,所以才有了今天我所看到的结果。

原本我也可以轻松增加个 else-if 就完成任务的,但我这个人有强迫症,不想再当一个 if-else 侠客了,好吧,开始写我的新功能。

写完之后的代码如下:

 1function readNewFile(file){ 2  // 具体功能封装 3  // ... 4} 5 6const modelObj = { 7  fn1(file){  // 功能1 8    // ...  9  },10  fn2(file){  // 功能211    // ...12  },13  fn3(file){  // 功能314    // ...15  },16  readNewFile(file){  // 功能417    // 新增加的功能18    // ...19  },2021  // 其他功能封装22  // ...23}2425function main(type, file){26  modelObj[type](file)27}

写完之后,我把代码提交给我的负责人看,看完之后,没错,你们看完可能也会问,你这不是没事给自己找事干嘛,明明可以增加一个 else-if 完事,你却额外增加了这么多代码?

没错,功能我实现了,代码多出了几乎一倍,反倒被要求重新改回原来的 else-if。鹿哥性格你们又不是不知道。我说,对不起,这是我的写代码习惯,正当我解释为什么要这样写的时候,负责人说,行了,先这样吧。

虽然心里有一万句不爽,但是我还是默默的转身离开了。

小结

这就是我刚刚实习的时候,碰到的第一件比较棘手的事情,我很理解负责人的心情,毕竟项目快速上线要紧,但是我认为给别人留条后路,就是给自己留条后路。

鹿哥,此话怎说,怎么感觉你话里有话。而且你还没有说为什么你要这么麻烦的去增加功能?

好吧,不卖关子了,其实这样的写法并不是我自己发明的,而是设计模式中的策略模式,可以说是老前辈在几十年的项目中总结出来,至于为什么这么写,肯定是有它的道理的。

我们先分析一下,上方原始代码的缺陷有哪些?

1、最明显的缺陷就是每个 else-if 中的代码有一堆实现功能的逻辑。一旦 else-if 出现问题,整个 else-if 中的其他功能全都不能用了。

2、如果增加一个功能,需要无限的叠加 else-if。

这两个看起来并没有什么毛病呀?别急,听我慢慢细说。

为什么把每个功能抽离成函数?因为像这种老项目,已经被很多前辈写过,项目很容易出现问题,一旦出现问题,很难定位代码,我们更不可能找到离职的员工询问具体哪出错误了。

如果我们单独抽离成函数,当该函数内部出现问题的时候,我们通过断点调试,可以直接定位问题出现在哪里。而不像以前在if-else 海洋里探索定位问题。

而且每个函数单独封装起来,因为遵循设计模式原则之一,单一功能原则。每个函数只能干一件事,每个功能都是独立分离的,这样尽最大可能实现功能函数之间的解耦。

有关第二点,为什么会设置一个对象映射,而不是继续增加 else-if?

这次我们增加一个功能,可能几年之后,客户需求有变,需要再增加一个功能,而增加功能的人换了,那么这个增加功能的人,不必担心原来的功能逻辑实现,只需要在这个对象中增加一个函数,在函数内部增加一个功能实现就 OK 了。

而且整体看起来,代码规范和整体的代码结构非常的清晰,不止于一旦出现问题,在修改过程中导致其他地方出现问题,从而影响项目的开发进度。

做完之后,我直接把我的代码扔给了我们公司的测试小姐姐,小姐姐对我笑了笑,咳咳,后来.....

可想而知,测试小姐姐在测试的时候,不用再把整个 else-if 拿过来测试了,而是直接拿我写的功能函数,只测试增加的功能就完成了。

回到最初那句话,给别人留条后路,就是给自己留条后路。我给测试小姐姐留了一条后路,后来就... (你们懂得)

最后

这件事情,让我产生深刻的感悟。如果能用哲学中老子的“道”去阐述的话,将复杂的问题转化为最简单的哲学思想,然后直至事物的核心与本质。

老子同时将“道”称为“无”和“有”,“因为它没有形象,所以是“无”;因为它真实存在,所以是“有”。

那么实际开发项目中,项目最初的本质就是设计模式的运用,设计模式的核心思想就是「封装变化」。就是变与不变,变化的是扩展,不变的是稳定。变与不变又可相互转化。所谓有形化为无形,有法化为无法。

正所谓,道可道,非常道,名可名,非常名。玄之又玄,众妙之门也。

©著作权归作者所有:来自51CTO博客作者mb5fe1601ede528的原创作品,如需转载,请注明出处,否则将追究法律责任

更多相关文章

  1. 再来 6 个例子教你重构 Python 代码
  2. 【代码实战】华为应用市场专家在线直播AppGallery Connect 服务
  3. 真香!GitHub 核心功能都免费开放了
  4. GitHub 热门:别再用 print 输出来调试代码了
  5. Hard 级别难度?桶排序几行代码搞定!
  6. 推荐一个项目:数据结构和算法必知必会的 50 个代码实现
  7. 十大经典排序算法动画与解析,看我就够了!(配代码完全版)
  8. VUE~~~通过首页链接到功能点对应的tab页(同一页面,不需打开多个页
  9. VUE~~~table编辑列功能

随机推荐

  1. 芋道 Spring Boot WebSocket 入门
  2. 洞玩年!刚面世的黑洞照片快被玩坏了!
  3. 直观讲解一下 RPC 调用和 HTTP 调用的区
  4. Apollo 源码解析 —— 调试环境搭建
  5. 白嫖七牛云作为个人博客免费图床
  6. 第九周作业
  7. 芋道 RocketMQ 安装部署
  8. Mybatis-Plus 真好用(乡村爱情加持)
  9. 国产微服务网关 APISIX,有点意思,直接开锤,
  10. 程序羊有知识星球了