“绞杀者模式真是一个绝妙的隐喻”,新进架构组的资深工程师兴奋地说。
X公司的W软件是一个遗留系统,就是通常意义上的遗留系统,不是Michael Feathers说的那种“没有测试的系统就是遗留系统”的那一趴。
从第一行代码算起,这个系统已经十几年了。最初写代码的人年纪大已经退休了,较为年轻的,也早就不是dev的角色了。偶尔在集团的活动上,坐在领导位上的某些人回忆峥嵘岁月时,经常提起这个系统,在他们的话语中,这个系统代表着“跨时代”、“先进”和“优越”。
往往这个时候,现在还在维护它的这些小伙伴往往报以苦笑。曾经“跨时代”、“先进”和“优越”的系统,现在就像一个年迈的老人。不复当年的矫健和灵活。
往往做一些简单的业务改动都需要好多的工作量,最可怕的是做了改动没人知道会不会导致别的功能崩溃,时间太久远了,没人能说明白整个系统的全景。
而且曾经先进的技术不再先进,在系统刚开始那几年,还能跟着做一些技术栈升级,走在技术的前沿上、甚至过于激进,比如及早地拥抱的Java 以及Spring。后面业务越积累越复杂,某次升级导致了一次事故以后,再也升级不动了。
至于基础设施,在运维小伙伴废了九牛二虎只力之后,成功地“上云”了,但是运维方式跟原来没啥太大区别。
团队中的所有人包括业务、开发和运维都被这个系统折磨着。
虽然业务领导一再表示理解,开发小伙伴还是在他们的眼神里感受到了对于工作量的质疑。
“一个button 你告诉我要开发一周,你忽悠谁呢?”
基础设施小伙伴天天要为这个系统加班,在支持这种系统的变更。很明显,这种系统发布是要停机的,好几次差点一个通宵没上线成功。当时几个熬了一个大夜的开发和运维,脑子都愣了。理智告诉他们应该回退,但回退只是理论上可行。
而“陪着”一起加班的“监工”项目经理一直在旁边假装嘟囔“已经给用户发了明天的上线内容了啊”
潜台词就是“你们快想想办法,反正我不接受上线失败”。
据当时上线的技术和运维说“有那么一霎那就想从楼上跳下去”。
最不满意的要数业务人员了。每次绞尽脑汁想到的好点子,送到开发那里要么是这么做风险很大,要么就是这个不能做,而好不容易有个双方都满意的点子,等到上线已经是仨月以后了,这个时候黄花菜都凉了啊。甚至有一次,一个非常合理的需求,上线后导致了 P0 级的 Bug。
技术人员都跟业务说了“需求提得非常好,下次别提了”。
后面大家觉得这么痛苦一定是出了什么问题。但是到处都是问题,到底哪个才是真的问题呢?有人说,是不是架构出了问题。所以部门组织了架构组。架构组是一个虚拟的组织,由日常团队里的骨干组成,大家日常仍然进行苦逼的开发,但每周都会抽出时间来对项目上的问题进行讨论。
一次次地问题,大家发现项目的结构十分地不合理。比如明明是一个东西被放在了两个模块里,被两个团队维护。线上订单和线下订单虽然支付方式不同,但在财务概念上是一个东西,但当时线上系统和线下系统都做了一套财务相关的功能,每次涉及这部分的需求改动,都需要负责财务的业务小伙伴相互协调步调。而在一个“有那么一霎那就想从楼上跳下去”的系统里,协调步调是很难的一件事。更可怕的是有的时候,步调没协调上,好几次线上事故就是这么产生的。
于是大家开始脑洞,如果抛开“历史包袱”,直接构想系统的结构应该是什么样子。
毕竟是自己天天打交道的系统,没多久“脑洞版”的系统设计新鲜出炉了。大家假设系统是按新需求构建的估算,工作量少了一半,原来需要 20 人天的工作量现在只需要 10 人天就可以完成了。
架构组不禁沉浸在系统是按新的结构编写的美好幻想中。
现在问题就变成了如何让领导同意“重写”这个神圣的项目了。
“这不可能!”领导说。事实上,'重写'计划在几年前被执行过,事情坏就坏在这个系统是正在被使用的系统。现在每周都有 30 多个新功能被计划添加在这个系统上,这个数字还在持续增加。

于是“新”、“旧”系统成了龟兔赛跑:“新”系统一边在按照“新”设计实现旧系统的功能,一边还要做新的功能。显然上线一个只有两年前版本的“新”系统没啥实际意义。
投入了大量的人力进行开发,结果过了半年,发现“新”系统添加一个新功能比“旧”系统快不到哪里去。显然“新”系统也被“腐化”了。
问那些当时雄心壮志的“架构师”,他们也是满肚子委屈。虽然技术人员争先恐后地加入新系统团队,可在公司方面,这是一个没有啥“贡献”的改造工程。只是因为这帮技术人员“不专业”,导致了系统改不下去了,所以在投入方面限制得很死。在技术负责人的一次次劝说下,可能是因为跟这个系统的渊源,或者单纯地被问烦了,领导同意了重写。新架构团队只有维护“旧”系统人员的十分之一。
在只有这么点人的情况下,又要追赶“旧”系统的进度,又要尽快把“新”系统投产(不然欠下的功能越来越多了),成本三角定律再次生效:当范围、成本、时间固定的情况下,被牺牲的只有质量。
这个时候,理智的团队叫停了“龟兔赛跑”,很明显“新”系统这只“兔子”失败了。
“所以,不可能说服管理层实施一个重写计划了是么?在不重写这系统就快崩溃的情况下?”
“是的,确定肯定以及一定,毕竟尝试过然后失败了不是么?”
“所以你的建议是我们干脆放弃,要么跟系统一起玩完或者赶紧找个正经班上?”
“也不是没有办法,不知道你们听说过绞杀者模式么?”
“就是那种新系统逐步取代旧系统的方式么?”
“绞杀者模式真是一个绝妙的隐喻”
于是技术团队开始内部“绞杀”,他们开始瞄上的是邮件发送系统。这个系统很小,而且跟业务关系不大,团队很轻松地就完成了替换。现在如果新需求里有邮件发送功能,只需要一行代码就 ok 了。“绞杀者模式真是一个绝妙的隐喻”
于是信心百倍的团队瞄上了订单系统,这是系统中最痛的点,而且性能压力很大,解决了它能给团队带来巨大的收益。开发团队像重构邮件系统那样从开发团队里抽出几个人来进行“新订单”系统的开发。
一个月过去了以后,由于“新订单”开发得比较仓促,开发团队对它的稳定性没有信心,加上一系列的新需求的开发压力,开发一度停滞。新订单的开发人员的技术水平不言而喻,但是业务不那么了解,梳理业务也花了很久时间。而核心系统嘛,新增需求也逐步积累起来了。这时候发现这个“新订单”系统又变成了新一轮的“龟兔赛跑”。
“所以,绞杀者模式只适合边缘功能?那我要它有何用!”
技术圆桌又一次召开。
“果然行不通啊!”
“绞杀者模式是一种理想的情况吧,现实中压根没有这样的条件。”
“所以,应该放弃助人情结,尊重系统命运,等哪天真的崩溃了,自然需要重新开始搭建了。”
“有没有可能我们落地绞杀者模式的姿势不对呢?”
“还能怎么不对,不就是新的代替旧的么?就是新系统把旧系统绞杀掉啊”
“如果只能替代掉那种周边系统,这个模式就太逊了。”
“等等,我找到了 Martin Fowler的博客,这里面说的绞杀者模式跟咱们想的有点点差异唉”

“绞杀者这个名字,其实是一种植物的名字。是澳大利亚的一种榕树,这种榕树会寄生在别的树里,一点点地把宿主替代掉”
那么这次“绞杀”行动失败的原因,好像找到了:
“所以,我们的系统还有救?”
“是的,我觉得我们的新计划应该叫做遗留系统植树计划,只是播种的是绞杀榕这种树”
“对,我们在需要变更的系统中按照新想法小步的重构,主要业务还是在旧系统中,用 API 路由的方式一个 API 一个 API 地迁移到新系统,在新系统能独立之前,主要的逻辑还是在老系统中直到可以取代掉这部分。”
“但是我仍有一个疑问,就是如果这种散落地重构,如何才能保证我们的‘新’系统是我们期望的呢?”
“好问题,我们可以开一个工作坊,就像我们之前开的那样,把目标系统设计用图示画出来”
“也就是遗留系统改造的步骤是:第一步设计目标系统、第二步规划演进路线、第三步逐步改进系统;其中第二步和第三步主要是使用绞杀者模式是吧?”
“对对对,绞杀者模式真是一个绝妙的隐喻。”
这是一个对Strangler Application的不够“雅达”的翻译导致的有趣故事, Martin Fowler在2019 年正式把Strangler Application重命名为Strangler Fig Application,中文可以译为“绞杀植物应用”、“绞杀榕应用”或者“绞杀无花果应用”,这样就不会产生错误的理解。但“绞杀者模式”的翻译传播如此广泛和深入人心,导致这种修改难以得到传播。软件工程中有很多命名都是一些有趣的隐喻,但同时又因为文化、经历的不同导致难以传达本身的意思。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。