背景
就像晓强在第一个故事开篇所介绍的那样,如今,我们所交付的典型软件已经变成了由若干个Cloud Native Application所组成的分布式的微服务应用,但是在我们所服务的组织中,仍然存在着类似下面的这种巨大的老旧的单体应用,我们称之为遗留系统。
有些遗留系统仍然在组织中扮演着重要的角色,持续为客户提供着价值,而有些则已经成为了组织发展的瓶颈,无法适应业务的快速变化。这个故事便是关于我们是如何帮助客户有效的维护、提升、最终摆脱这些遗留系统的。
正文
提到遗留系统,我们并不陌生也不缺乏案例。过往的大型项目为我们提供了很多值得分享的经典案例,能够从这些经验和总结中感受到在这些项目中所克服的挑战。这些挑战分别来自于:
- 如何有效的积累遗留系统的上下文
- 如何对遗留系统进行维护和变更
- 如何能平滑的完成对遗留系统的技术迁移
积累上下文
万事开头难,当我们开始任何一项交付工作时,最关键的问题便是如何能够快速建立业务和技术上下文。而当我们开始接手一个遗留系统的时候,这个关键问题变得更加复杂和困难。
遗留系统的上下文就和一个没完成的拼图一样,碎片散落一地。有些信息只存在某些人深深的脑海里,有些信息在巨大而且过期的文档里,难辨真伪。代码不会撒谎,但是动辄几百万行的代码很容易让你迷失方向.
在应对这一难题上,我们从以往经验中形成了一套行之有效的方法。
首先,通过沟通和询问客户团队的业务或技术人员去了解到尽可能多的信息,然后通过阅读文档或在可用环境中演示来得到更具象的认识,最终通过阅读代码来解除剩下的疑问,完成巨大拼图中的一部分。
但是在实际操作中确仍然不简单。往往情况是这样的,在经过多次沟通和在文档中查阅信息后,获得的信息往往和代码中的无法对应起来,使整个过程需要不断的反复。我在去年经历的一次遗留系统改造项目中就有一次类似的经历,团队被这个令人沮丧的过程打败,做出了一些基于已有信息的假设,最终给项目的交付造成了不大不小的风险,团队付出了很大的代价才保证了项目的顺利交付。
在获得了上下文后,如何保持信息能得到及时的更新并有效的将信息共享给团队其他人是紧接着需要思考的问题。Specification by Example为我们提供了很好的方式将所有信息有效的管理起来,构建一套和代码一起管理的可执行的Live Document。但是对于一个遗留系统,这仍然是一个漫长和繁琐的过程。在这整个信息收集和记录的过程中,团队需要展现强大的耐心才能有效的达成目标为后面的工作打下基础。
开展变更
对于有些遗留系统我们只需要对其持续的监控,保证其能够正常的提供服务。但是在大多数情况下随着客户的业务不断变化,也会产生对遗留系统进行变更的需求,来迎合这些业务上的变化。那么如何在不破坏遗留系统的前提下修改遗留系统便成了应对遗留系统的第二个挑战。
用我们所推崇和坚持的一系列敏捷技术实践可以为遗留系统变更提供一张很好的保护网。
- 在进行对遗留系统的修改工作之前,通过一定的单元测试覆盖,加上之前我们已经建立好的Live Document,能够为我们很好的提供质量保证。
- 通过建立针对遗留系统的CI/CD Pipeline可以使我们在修改遗留系统时快速的得到反馈,对变更进行及时的验证。
- 通过创建Stubs来Mock遗留系统的外部依赖则能帮助我们有效的缩短反馈环,可以大大增强我们对遗留系统进行变更的信心。
这些实践看起来和我们所交付的其他项目没有两样,但是当你需要为某个老旧语言编写的遗留系统提供单元测试覆盖的时候,当你的CI Pipeline需要支持一个老旧的商业中间件的自动化部署的时候,看似普通的技术实践则会变得困难重重。
这个时候将坚持这些实践作为原则变得尤为重要。这样才能为遗留系统的变更提供有效的保障。
技术迁移
当然仅凭耐心和原则是无法征服动辄几百万行代码的庞然大物的。应对遗留系统对技巧有着更高的要求。在这方面,我的ThoughtWorks同事们已经从过去的项目经历中总结和分享了很多应对遗留系统的技巧。特别是在对遗留系统进行技术迁移的过程中。比如:
- 影响结构图与特征草图的使用,帮助我们去梳理程序中各个模块之间的关系和依赖。
- Branch By Abstraction的使用,使我们可以逐渐的替换将系统中遗留的部分更新并剔除出去。
- Strangler Pattern的使用,让新老系统在一定的时间段内共存,使遗留系统能够平滑的迁移到新的技术架构。
- Feature Toggle的使用使我们能在部署后发现异常时快速的切换回老系统,使迁移风险降到了最低。
- 针对遗留系统的数据特点建立自定义的数据管道,完成遗留系统数据的迁移。
正是对这些技巧的灵活使用使我们真的做到了“旧的不变,新的创建,一步切换,旧的再见”。
写在最后
遗留系统是个难题,在应对一个巨大的遗留系统时没有捷径,同时也没有神奇的秘籍或令人目眩的黑科技。重要的是,团队需要意识到在面对一个遗留系统的时候我们需要具备:
更强大的耐心 - 去有效的收集和巩固遗留系统漫长发展过程中遗失的上下文。
更坚定的原则 - 去坚持敏捷技术实践,为遗留系统编织可靠的保护网给遗留系统的变更提供保障。
更丰富的技巧 - 去最大程度降低遗留系统技术迁移过程中对现有业务的影响,逐步平滑的完成遗留系统的迁移。