gitbook/遗留系统现代化实战/docs/511924.md
2022-09-03 22:05:03 +08:00

146 lines
14 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 07 | 遗留系统现代化的五种策略:重构还是重写?这是一个问题
你好,我是姚琪琳。
从今天开始我们正式进入模式篇的学习。这一部分我会带你学习代码、架构、DevOps、团队结构四个现代化中的各种模式这些模式是我们实战的理论基础希望你能牢牢掌握。
不过深入学习这些模式前,今天我们先从重构和重写的“两难”问题说起。到底是重构,还是重写?这是一个困扰着很多团队的问题。
重构吧,遗留系统积重难返,重构之路遥遥无期,三年、五年时间,可能也只是刚开了个头,还不如重写。
但重写就真的比重构好吗?遗留系统中最难获取的就是业务知识。当你问起一块业务时,得到的回答往往是:“没有文档”、“没人知道”或者“只能看代码”……没有业务,或者说没有需求,怎么可能构建出来一个新的系统呢?
那我们到底应该如何应对呢?除了重构和重写,还有没有其他方式呢?
## 遗留系统现代化的五种策略
Gartner在19年曾经有[一篇报道](https://www.gartner.com/smarterwithgartner/7-options-to-modernize-legacy-systems),提出了遗留系统现代化的七种方案。我把这七种方案做了整合,把它们整理成后面这五种策略。它们各有各的特点,而且分别对应不同场景,你要根据项目自身情况选择不同的策略或组合。然后,再应用后面要讲的模式来落地。
### Encapsulate
第一种策略是**Encapsulate**,也就是**将遗留系统中的数据或者功能封装成API供外部调用**。
我们在[第一节课](https://time.geekbang.org/column/article/505740)里提到过遗留系统中蕴含着丰富的数据资产但是因为技术和工具落后导致它难以与新系统集成这些数据被封印在遗漏系统中成了数据孤岛。比如早期的银行或民航软件很多都是部署在大型机上的。企业非常希望开发手机App这样才能更好地为客户服务但却很难访问到主机上的这些数据。
同样地遗留系统中还有一些功能十分重要其他外部系统需要这些能力来构建业务。比如一些公文流转的工作流可能构建在基于Lotus Notes的办公系统中但如果企业想要开发移动办公App并在App中复用这套工作流也是困难重重。
问题虽然棘手但事到临头工程师们总要想办法应对。结合刚才说的情况我们可以封装这些数据和功能形成API供这些移动App或其他外部系统使用。如果遗留系统本身就是基于Web的可以在Web系统上直接构建API如果不是可以选择构建一个全新的Web API来部署并提供服务。
这样做的好处是以较低的成本和风险尽可能满足外部系统的需求。你无需对遗留系统做较大的修改只是增加一些API而已。遗留系统本身不会被优化但它可以通过这些API对外提供能力。
还有一种情况,我也建议你使用封装的策略,那就是当你有一个第三方系统,希望扩展它的功能,但只能访问它的数据库,却无法修改代码的时候。
这时有些团队采用的方式就是直接连它的数据库,并在已有的系统中基于这些数据构建新的功能。我不建议你这么做,直接连数据库固然简单,但由于你可以访问它所有的表和列,距离混乱也就剩一步之遥了。
我建议你基于这个第三方系统的数据库构建一个Web API来向其他的系统提供你想提供的数据和功能而不是暴露全部的数据。
我这里也稍微剧透下,封装的策略落到具体应用的时候,衍生出了很多相关模式,比如**数据API模式**、**功能API模式**等等。我会在后面的课里再详细展开。
### Replatform
第二种策略是**Replatform**,也就是**替换运行时平台**。这种策略不需要对代码大动干戈,只需要改动很小一部分。到了新的平台后,软件的功能和特性仍然保持不变。
比如很多银行或民航软件还是基于COBOL的主机系统把它们从大型机上迁移到Linux或Windows环境就会甩掉昂贵的主机成本。
再比如早年间开始构建的系统由于种种原因很多是基于商业软件的想升级就要花一大笔预算。很多企业为了节省这部分开支会尽量避免升级也导致系统最终变成了遗留系统。你可以通过Replatform策略来解除对商业软件的依赖例如用Tomcat来替换WebLogic。
或者像.NET这种技术栈也十分有必要从.NET Framework迁移到.NET Core或者.NET 5。而Python从2升级到3、JDK的大版本升级等等也都属于Replatform。
在使用Replatform时你只需要对代码做少量更改以适配新的平台。这样只通过较小的成本就可以降低基础设施的成本并提高性能。
还有一种迁移我认为也可以看做是Replatform虽然它并不是替换运行时平台。那就是迁移代码版本管理工具。比如你把代码从SVN迁移到Git中不需要修改任何功能代码但却可以享受新的代码管理平台带来的好处。
### Rehost
第三种策略是**Rehost**,也就是**将应用程序或组件部署到其他基础设施中**如虚拟主机、容器或云。这种策略完全不需要修改代码而只需要迁移部署的环境甚至都不需要重新编译因此这种迁移方法也有个很形象的别名叫做“lift and shift”就是原封不动地拎起来转移到别的地方去。
我举个例子来说明如果你的公司有一个SAP的ERP系统可以将它从本地的数据中心迁移到AWS或GCP中。
Rehost可以让你在完全不修改已有系统的情况下快速上云体验云环境带来的弹性、安全性和高性能并且迁移过程也能做到很平滑。然而由于没有任何适配也就无法充分利用云原生的优势因此还需要对系统内部的代码和架构做进一步调整比如将单体架构拆分为可以独立运维的微服务。
### Refactor/Rearchitect
第四种策略是**Refactor和Rearchitect**,它们是指**在不改变系统外部行为的前提下,对代码或架构进行调整、优化,以偿还拖欠已久的技术债务、改善非功能需求、提升系统健康度**。
**Refactor主要是指代码级别的重构**比如你可能用Sonar等代码扫描工具扫描出了很多代码坏味道、缺陷或隐患修复这些问题的过程就属于Refactor。这和我们平时说的代码重构基本上是一个意思。
**Rearchitect是指架构级别的重构**它包含两层意思。第一层比较好理解就是指从单体架构到分布式架构的这种架构调整。第二层是指不改变部署单元之间的关系而是对单个或多个部署单元内部进行模块化或分层重构。由于这种模块化和分层也会涉及很多代码的调整所以这种Rearchitect往往会和Refactor同时进行。
后面你学到代码和架构现代化的内容时会看到很多Refactor/Rearchitect相关的模式。这些也往往是遗留系统现代化中最有挑战也最有意思的部分。
### Rebuild/Replace
第五种策略是**Rebuild和Replace**,都是指**对遗留系统进行替换**。它们两个替换的范围和程度不同。**Rebuild**可能是**对应用程序的某个组件或某个服务的重新设计或重写**,但会保留其原有的业务范围和业务规则。而**Replace**是指**彻底淘汰应用程序的所有组件,去构建或购买新的软件**,同时会考虑添加新的业务需求或移除某些旧的业务需求。
我在[第一节课](https://time.geekbang.org/column/article/505740)提到过遗留系统中的业务知识是严重缺失的不仅没有遗留下来的文档供我们查阅也没有任何一个人能说清楚全部的业务细节。在这样的基础上实施Rebuild或Replace风险和成本都是相当高的但相对来说收益也是最高的一旦替换成功就可以彻底摆脱原来的遗留系统了。
下图是对上面五种策略的一个总结,你可以从中看出它们的收益、风险和成本(用面积表示):
![](https://static001.geekbang.org/resource/image/73/bf/735968254f34d2eecbe73f5f0bed34bf.jpg?wh=3122x1870)
### 其他策略
除了上面的几种策略以外,对于遗留系统来说还有一些应对策略可以选择。不过由于不涉及到代码、架构或运行环境的变更,我没有把它们作为遗留系统现代化的策略。
其中一种是Retain即保持系统当前的状态不做任何修改或更新。对于尚可满足使用的遗留系统来说这无疑是风险和成本最低的策略。我在[第五节课](https://time.geekbang.org/column/article/509535)说过,使用人数不多、需求很少、只需要一两个人维护的遗留系统,就可以使用这种策略。
还有一种是Retire就是评估完工作量、使用情况和业务价值之后选择完全停止使用的一种策略。有的时候系统已经没有什么人用了或者类似的功能在其他系统中可以替代你就可以选择让这个旧系统彻底退休了。
## 你应该选择什么样的策略?
面对如此眼花缭乱的策略,你恐怕更加无所适从了吧?别担心,接下来我就来帮你梳理一下如何选择。
到底是Replatform还是Rehost是Refactor还是Rebuild是Rearchitect还是Replace其实我们还是要依据目标和系统现状做判断。
先看最终目标,第五节课我列出了企业遗留系统现代化的四个目标,即业务敏捷、运营效率、客户洞见、系统韧性与弹性。
对于业务敏捷来说Replatform和Rehost通过替换运行时环境和上云可以提升部署频率特别是Rehost可以显著提升系统在遇到故障时的恢复时间Refactor/Rearchitect通过改善代码和架构的质量可以缩短需求交付周期减少线上问题数量而Rebuild/Replace由于在某种程度上做了替换也可以大幅度提升业务的响应力和交付质量。
对于运营效率来说Refactor/Rearchitect和Rebuild/Replace都可以提升价值流效率。而要想改善客户洞见最有效的方式还是Rebuild/Replace。在系统韧性与弹性方面Rehost显然是不二之选。
我们要结合当前遗留系统的现状和想要提升的目标,做综合判断,对于不同的模块,也可以选择不同的策略组合,来实现一个完整的业务目标。
比如遗留系统中的有些业务需要提供7x24小时的高可用服务类似银行转账、保险报案等模块。但这些模块很有可能还位于单体的“大泥球”中和其他模块有着剪不断、理还乱的关系。
为了支撑这些需求我们可以先采用Rearchitect的模块化策略结解耦模块之间的关系然后再用Rearchitect的服务化策略将这些模块拆分成独立的服务最后再用Rehost策略将这些服务部署到云上以提升系统的可用性。
当然如果由于系统耦合严重模块化改造很难实施你也可以选择用Rebuild策略重写这一部分模块。
再比如一个部署在WAS v6上的Java Web遗留系统由于只支持Java EE 1.4,技术栈严重落后,已经很难在市场上招到人来维护了。
这时可以先选择Replatform策略将WAS替换为较新版本的Tomcat以摆脱昂贵的商业软件然后再次使用Replatform升级Java的版本包括所依赖的第三方工具这样就完成了整个技术栈的升级。
如果企业认为当前遗留系统已经彻底无法满足业务的需要且具备足够的资源来构建新的系统就可以使用Replace策略来彻底替换旧系统。同时在遗留系统并不是很大但重要性又相对很高的情况下也可以考虑Rebuild/Replace。
这里我一直没有提Encapsulate这种策略是因为它有自己独特的适用场景也就是与其他外部系统集成的时候。
## 小结
又到了总结的时刻。今天我们学习了遗留系统现代化的几种策略,不同的策略有不同的适用场景,我把它们总结到了一张表中。
![图片](https://static001.geekbang.org/resource/image/ec/d6/ecd8ff1b982116d6ff91e4f5bebb5cd6.jpg?wh=1920x1135)
你要记住的是,一定要根据项目的情况来选择不同的策略组合。不要上来就大张旗鼓地重构或重写,一定要弄清楚想要的是什么。除了重构和重写,你其实还有很多选择。
从[下节课](https://time.geekbang.org/column/article/512658)开始,我们马上进入各种模式的学习了,你准备好了吗?
## 思考题
感谢你学完了今天的内容。我给你留的作业是这样的:
假设你是一个项目的技术负责人,你的项目基于.NET Framework 4.6.1而该版本即将在这个月2022年4月“寿终正寝”。为了避免潜在的安全风险你不得不将.NET版本进行升级假设系统当前部署在Windows虚拟机上
这时你有以下三个选择:
1.升级到.NET Framework 4.6.2版本,几乎不用对代码做任何修改,只需要升级一下各个部署环境的虚拟机即可,保守估计三天之内也能完成升级并上线。
2.升级到最新的.NET Fremework 4.8版本可以获得更长的技术支持还能使用新版语言的特性以提升开发效率。但有些旧的第三方库并不支持4.8,需要升级或替换。你可能需要两周到一个月的时间来完成全部升级。
3.升级到.NET 5以充分享受跨平台和容器化的优势系统也将彻底摆脱Windows的束缚。但代码需要改动的地方很多几乎所有第三方依赖也都需要升级。预计需要五到六个月的时间才能搞定。
你会做出什么样的选择呢?补充一句,如果你不熟悉.NET的版本和特性可以自行搜索一下。
本次作业没有正确答案,在我看来,任何一个选择都是可以接受的。你可以根据自己的思考给出答案,并说明理由。必要的时候,也可以自己添加一些约束条件,来支持自己的选择。
期待你的分享。如果你觉得今天这节课对你有帮助,别忘了分享给你的同事和朋友,说不定就能帮他解决一个难题。