前言
这篇文章适合给那些要处理Legacy System(旧系统)的朋友们看,如果你们团队有系统的code是一团乱,而且完全没人知道他为什麽可以动的话,你可以参考一下这篇演讲给的建议。
演讲总结
这篇文章讨论的主题是我们要怎麽处理Legacy System。
那什麽是Legacy System呢?其实就是一个正在线上跑的旧服务,而且这个旧服务非常难维护,改进与扩展。而会这样的原因,通常就是因为它overloaded了,承载了超过原本设计能负荷的事情。
一般来说Legacy System的产生原因是基於一系列的紧急事故(emergency),因为人力与时间不足,所以我们不断的在原本的系统上加上应急方法(workaround),导致欠下一技术债(technical debt)。而有些状况则是因为写原本系统的人离开了,也没好好交接好,想淘汰但又不太确定是谁在用。
无论成因为何,为了处理这种系统,我们可以想到三种方案:
方案一:继续在上面加东西
这通常发生在没时间或没资源的情况下,基本上是下下策,毕竟你不知道什麽时候这个系统会完全扛不住爆炸。
方案二:完全重写一个新的系统
很多时候这真的是蛮不错的选择,但想必他也有很多问题需要考虑:
- 没时间重写,或只来得及写一半怎麽办。
- Legacy System的复杂性总是被低估因为成功者谬误(success bias)。
- Bug需要重新被发现与修正,前人踩过的雷往往会需要重踩一次。
- 新的feature会被delay。
- 资料迁移(data migration)过程总是非常痛苦。
- 还是需要同时维护新旧系统。
方案三:渐近式重写(progressive rewrite)
Progressive rewrite又被称为扼杀者模式(Strangler pattern)。意思就是在既有系统上慢慢抽换掉内部元件,直到整个系统都被重新写过。
这个方式虽然很安全,但是不代表很直观。而它通常花的开发时间会比整个重写还要来的久,但是好处是,比起重写後要完美取代旧系统所需要花的时间可能少了些。因为很可能会少了後面修修补补的部份。
要怎麽做到progressive rewrite呢?
要回答这个问题,讲者想先讨论:什麽是code quality?
当我们讲到code quality,很多人会想到TDD、test coverage、design pattern这些东西,但这些其实并不是评断code质量的依据。
真正判断code quality的是,你有没有办法保持快速deliver feature或快速发现bug。如果你的code quality很高,意思就是对於新的feature你的开发时间并不会随着codebase增加而巨幅增加,理解难易度、debug难度亦然。
因此保持好的code quality的重要关键是模组化(modularization),如果系统可以分割清楚每个元件的任务,便可以轻易抽换内部元件,或轻易增加新功能上去。
有了这个概念後,我们就可以来看应该要怎麽回春(rejuvenation)
- 先讲低onboarding这个legacy system的复杂度,让新使用者可以快速的上手与设置好工作环境。
- 写好end to end test,确认外部系统与他沟通时的结果是可预期的。
- 将code想办法切成小module。
- refactor系统让他可以好拆开,与变成可抽换式的系统。
- 重写一个一个module慢慢取代旧有系统
- 不要丢弃你的旧code,未来可供参考。
Source code rejuvenation is not refactoring
而要注意的是rejuvenation与重构(refactoring)是不同的。
Refactor是修正内部的实作方式,是一种technical的improvement,所以业务逻辑是不会被改到的。但是Rejuvenation是整套的翻修,是会牵扯到要重新设计product本身,所以通常rejuvenation是需要产品经理(PM)们的参与的。
个人心得
这篇演讲对我来说没有太多insight,不过自己倒是在处理legacy system是真的蛮有经验的,毕竟我跟着公司从无法scale的monolithic,一路走到现在拆开来的microservice;加上组织内部一天到晚在reorg,各种handover takeover常常中间都会有资讯消失。所以处理legacy system基本上是每天在做的XD。
什麽时候要重写整个系统?
虽然上面讲的是渐近式重写旧系统,但还是有少部分状况还是重写整个系统比较好的。就是当我们产品要整个重新设计的时候,因为我们不是只是把旧有的code变整齐而已,更多是要重新思考与汰换旧的产品。大忌是,不要搬移与重写没有在用的东西,如果不确定的话就想办法去查出来,看是看request的source还是做公司级别的impact analysis。
至於怎麽做refactor,来自Slack的Maude Lemaire之前有给个talk:How to get away with refactoring。里面讲的主要是Slack之前refactor系统去增加performance的一些细节,对於没有refactor或rejuvenation的人可以看看。
关於淘汰旧系统
不过虽然上面讲了很多,但我觉得淘汰旧系统其实最难的不是重写的部份,而是处理依赖(dependency)的部份。deprecation最痛苦的就是你不知道有没有人在用,而就算知道有人在用,也不见得知道是谁在用你的api。
我们公司一般会使用一个叫Impact Analysis的流程去让整个组织的stakeholder去确认改动与每个team有无关系,但做完後才是痛苦的开始,因为你要去要求他人迁移去用新的系统,或者重新讨论使用的需求,但极有可能大家没时间处理这件事。所以到最後整个搬迁的时间整个就有可能被拉的很长。我们都会开玩笑的说,这种情况就应该要做chaos engineering,直接把旧的API下掉,等大家出了error之後就自然会有动力去迁移了(误)。
不过这里想讲的重点是,因为会有很多依赖关系的问题,所以及早的开始做这些分析与调查,及早的kick-off讨论deprecation的计画,必且同时平行的做掉那些没有相依问题的地方,才有办法早日脱离苦海。