别再为没时间重构找借口:每年两次机会,治愈你的代码洁癖、安抚你的工匠之心! - 阿里技术
阿里妹导读
本文分享了作者对于重构的经验和看法。
一、引子
回顾曾在开放平台工作台的三年,发现自己主要是写业务为主。虽然和同伴们一起参与主导过从组件化到平台化、配置化到定制化的能力建设,但更多的精力也参与在客户拜访、ISV培训、数据分析和业务决策,这让我有了对业务方向的提前感知和判断,使得在技术侧能够前置准备,更好的服务业务目标。能力建设上没有什么阻力,反而省去了很多描写技术的笔墨。
其实想想,作为一名普通程序员,也许我写什么并不值得别人重视,但对自己也许挺重要。因为这说明我有自己的思想和好恶。如果没有这些,也便没什么意思。另外作为普通员工,我也想改改以往写东西时那种有点貌似全局视角和方正规矩的风格,例如像《OA审批支持钉钉套件业务的探索和思考》、《钉钉工作台走向平台开放的探索和思考》、《钉钉工作台开放能力建设阶段性总结》,想着着眼处应该可以放得更细微一些,风格上可以更随性一些。譬如朝露,去日苦多,何必那么时刻严肃呢。
二、要还债
主要近期经常听人说道,被一些历史悠久的代码所坑。架构调整,人员更迭,种种原因,代码问题既无记录也无说明,每天在这样的代码里挖呀挖呀挖,挖到的一定不是颗珍珠。这些也许该被称为技术债务吧。
技术债务有不少教科书介绍过怎么分类以及针对每一类该持有的态度。我仅从个人经验来尝试理解下起因:
第一类,是善意所为。原本会有一个更优的方案,但由于当下时间、成本等方面限制,权衡决策选择了降级。可能损失了一定的扩展性,但带来了性价比,也为业务争取了时间。通常在业务需要快速验证、需求有时间限制或设计新的架构时出现。决策者很清楚现在有什么问题,未来将带来什么问题,影响到什么,从而在方案中也会考虑未来逐步去演进的计划。什么情况该补偿什么,哪些可以暂时先不做但什么情况下需要做,短期长期通盘考虑,只要比影响到来提前那么一点点完善就好。
这一类留下的债务,如果有人跟踪,通常能在后期进行有计划的迭代偿还,有点类似于还房贷,还可以选择还款方式是等额本息还是提前结清呢。但困难的是,团队需要将代码设计思想传承。如果前面的人轻轻的走了,不留下一片云彩,后来的人没有了解到代码设计进化的方向,不能追踪,这就成了坏账。
第二类,是无心之失。在编码时是实现了功能,但并没考虑到对未来或全局的影响或者考虑不够周全。产品验收测试是看不出任何问题的,短期内或者代码不迭代也反映不出什么问题。经过一定时间的需求迭代后,路遥日久,则可能由于扩展性耦合性等原因,变更举步维艰。
这第三类,权且称为有意失之吧。且就看眼下,能快速完成,这不仅能得到点赞,还省心省事呢。以后的影响,呵呵,谁知会影响到谁呢,何必现在花这么大心力去自寻苦恼呢。
去年中我从工作台调到了OA,这是个老牌应用,过去几年经历几度调整经历过大规模的人员更迭。在我看来,好的代码就像诗歌、音乐,有种天然的节奏感和韵律感,仿佛眼前出现一位仙女,凌波微步,罗袜生尘,吸引你紧跟上去。反之,则似盲人摸象,看不清猜不透陷入泥沼之中。OA里有好的代码,但也有好多年前的遗留,刚看到时也是有种要还债了的感觉。
但大流量业务,稳定性压倒一起,没有技术文档存留、也没有口口相传的心法,先得静默观察,不宜乱动。遇到问题先记下来,这样就积累了一张技术债的表。当然新的一年里,我们也积累了很多新需求的技术方案,这样可让后面来的人有迹可循,万一要还债也会轻松一些。
三、等风来
若是平白无故的发起一个重构,在业务团队,几乎不可能,除非是可能引发或已发生重大故障了,要对应处理。债务表里已经有了不少了,方案也思虑过一些了,万事俱备,只欠东风。风是什么呢,可能就是日常的迭代需求和团队共识吧。如若团队没有这样的共识,又不够开放,这样的想法可能只会使自己处于一个细草微风岸,危樯独夜舟的境地了。如何判断风向和风级,可能就是仁者见仁的事情了。
四、风的感觉
我们曾经确实历经三年坚持代码翻新,消灭了远古代码,之后再没产生过线上故障,需求完成效率也上来了。可以感受下。
日常迭代的微重构,有很多:
- 例如设计师对第三方的组件UI做了设计升级,技术侧趁机使用配置化来快速实现组件的标题栏和外框样式,而不需要每个接入的第三方组件都去开发一遍。以后外观样式变化也可底座统一调适。
- 例如要新增一种应用列表组件,技术趁机将原有的6种应用列表类组件整合重构成一个组件,通过配置实现多种多样的新组件。
- 例如在对打开应用的功能增加新需求时,技术重构了原嵌套十几层的条件语句代码,后面还升级为了钉钉的通用组件。
日常迭代的需求(小风),像是东风的会有些特点:
1.较小投入,可以让完成本次需求变得更容易,以后再修改也方便。
2.修改范围不大,有明显影响边界,项目管理风险和线上稳定性风险都可控。
3.完成的人心旷神怡,带来愉悦感受。
大的风口也有:
- 我们曾经在移动端工作台支持客户定制的需求中,完成了移动端首页的架构升级,合并海外工作台、定制工作台、行业工作台等不同代码项目到统一的一个移动端底座项目。由原来维护多个项目,到只维护一个,减少了成倍的开发维护成本。
- 我们曾经在PC端工作台和移动端一样支持定制的需求中,完成了PC首页远古代码的架构升级,页面schema化、组件化。和移动端数据逻辑层复用,配置管理页面多端复用一套。同样降本提效。
- 我们曾经在UI体验升级需求中,前后端配合实现首页多级缓存降级方案,增强系统容灾能力和稳定性并提升页面访问性能。这原本仅仅是一个UI层的需求呀,可能原本只需改改样式呢。
这样的需求,有些共同的特点(6级东风):
1.需求涉及到待偿还技术债中的部分,且升级方案有助于需求完成以及面向未来更加友好。
2.需求有一定时长的研发周期和灰度周期,增加容错能力,减少本次重构或升级的上线风险。
3.多数情况通常都会动到数据模型,要项目组达成共识,前后端协同动作,口径一致。
几乎每年,产品上都会有一次大型的体验升级、一次大型的功能升级,这也就是业务团队技术同学的两次机会了。抓住它,会很治愈。
五、迎着风
前面写过一个见缝插针的在需求中完成一些力所能及的微重构的例子,例如 记一次迭代需求中的微型代码重构。
这一次,可来了一个首页导航升级需求。将首页的二级导航升级到一级导航,并且给用户新功能引导。
那么,借着这次东风可以做什么呢?
一是导航的配置化。可以通过配置实现在任何导航任何位置的红点、提醒、数字角标等。见上图右侧。
这么做的好处:
原导航代码的风格是有提醒、角标什么功能需求就写死在代码里。每次需求一改,就需要修改代码走发布,周期长、耗人力。配置化后,可实现快速响应需求。
二是新功能引导的组件化和配置化。见上图左侧。
这么做的好处:
1.统一掉散落在各个页面的新功能引导组件,实现页面间组件可复用。原来多个页面上都写过类似的功能,每次上新功能,都重写一份儿。再手动下掉或者干脆留着无用的代码。
2.统一掉新功能引导组件的逻辑。例如:
a.点击组件的关闭,则本组件不再出现,本地持久化
b.点击页面的跳转,则不再出现,本地持久化
c.组件曝光超过天数,则不再出现,本地持久化。可配置曝光天数
d.可配置是否仅老用户可见
e.引导的内容可配置
3.将容易修改的部分配置化,无需发布,实现快速线上变更。例如有些引导仅对老用户可见,有些新老用户一视同仁。有些要求曝光3天,有些要曝光一个月。这些差异化,都可通过配置来实现。
想改下写作习惯,却写得有点凌乱,果然是放任自己很容易,找回自己很难。希望自己不要气馁,再接再厉。这篇一不小心这么长,那么进一步的技术方案细节,如果有必要的话,就放在后续再聊。
露沾枝叶重,水漫泥径斜。
雨打花飞落,风吹草木折。
池鱼听风起,林鸟曲低合。
月明星尤寂,不识异乡客。