《遗留系统现代化》读书笔记(原则篇)

目录

以降低认知负载为前提:为什么遗留系统这么难搞?

怎样理解认知负载?

遗留系统中的认知负载

以降低认知负载为前提

总结

如何降低认知负载:活的文档能救命

什么是活文档

如何用活文档挖掘业务知识

为遗留代码添加注解

实例化需求最好的工件就是活文档

用依赖分析工具展示系统知识

总结

以假设驱动为指引:如何评价遗留系统的现代化成果?

脱离业务的技术改进都是耍流氓

什么是假设驱动?

在遗留系统中应用假设驱动开发

明确目标和度量指标

小结

以增量演进为手段:为什么历时一年的改造到头来是一场空?

什么是增量演进?

代码的增量演进

架构的增量演进

小结


本文地址:《遗留系统现代化》读书笔记(原则篇)_陆业聪的博客-CSDN博客

以降低认知负载为前提:为什么遗留系统这么难搞?

怎样理解认知负载?

认知负载(Cognitive Load)是指从事一件工作所要使用的脑力劳动的总和。简单来说,就是你可以用认知负载衡量你牺牲了多少脑细胞。

《遗留系统现代化》读书笔记(原则篇)_第1张图片

  • 内在认知负载是你掌握一门技能所必须要付出的努力,虽然不同的技能难度不同,但只要选择了一个,它的大小就固定了,掌握得不够必然就无法胜任工作。
  • 外在认知负载是信息的呈现方式,是我们着重要降低的,信息的呈现自然应该越简单越好。
  • 相关认知负载是在构建概念时要了解的知识,是要尽可能增加的,因为这些知识越多越有利于我们的工作。

我们要完成一项工作,就要在内在认知负载一定的前提下,尽量减少外在认知负载,增加相关认知负载。

遗留系统中的认知负载

遗留系统最大的认知负载其实是无处可寻的业务知识。因为它们是以“质量很差的代码”这种形式向人呈现出来的,因此有着非常高的外在认知负载。

下图是事件风暴的发明者 Alberto Brandolini 在讲述知识的分布时用到的图,有些知识只有曾经工作在它上面的某一个人知道,有些知识得去问 Bob,而有些知识就像一个谜。 《遗留系统现代化》读书笔记(原则篇)_第2张图片

遗留系统的第二大认知负载,是同样难以获取的系统知识。这里的系统知识是指系统的具体实现细节,包括模块的划分、架构的取舍,以及每一个技术决策的原因。这些知识也同样很难有文档可以一窥究竟,更遗憾的是,连代码都无法体现出每一个细节。

以降低认知负载为前提

以降低外在认知负载为前提的意思就是,我们进行遗留系统现代化时,所做的任何举措都应该是能够降低外在认知负载的。其实不止是遗留系统现代化,我们所有的工作都应该尽量去降低外在认知负载,从而简化工作本身。降低认知负载这一原则不光能作为方向指引,落到微观操作层,同样能帮助你科学预判改造过程中的每个决策。

总结

  • 内在认知负载是指从事一项工作必须付出的努力,比如学习 Java 知识、前端知识等;
  • 外在认知负载是指知识呈现的形式,代码越糟糕、越难读,外在认知负载越高;
  • 相关认知负载是指人们要学习一个知识所要付出的努力,在软件开发领域就特指业务知识。

《遗留系统现代化》读书笔记(原则篇)_第3张图片

 你只需要判断一下,当前这个事物、活动、决策所增加的认知负载是否更有利于我们完成当前和以后的工作。如果有利(比如学习更多的业务知识),就增加这种认知负载;如果不利(比如读一篇晦涩难懂的需求文档),就减少这种认知负载。

如何降低认知负载:活的文档能救命

什么是活文档

活文档(living document),顾名思义,就是指活着的文档,也就是在持续编辑和更新的文档,有时候也叫长青文档或动态文档。

如何用活文档挖掘业务知识

为遗留代码添加注解

可以通过在代码中加入活文档的方式,来降低认知负载。通过在代码中添加注解,分析代码生成各种可视化的图表。

实例化需求最好的工件就是活文档

所谓实例化需求,实际上指的是以现实中的例子来描述需求,而不是抽象的描述。我们在开发时,可以将这种需求转换为测试,这种以实例化方式描述的测试,也是一种活文档。它们不但很好地展示了业务知识,而且是随代码更新的。

用依赖分析工具展示系统知识

我们可以通过依赖分析工具,建立一张遗留系统的地图,这样就可以快速知道一个业务是由哪些模块组成的。对于存储过程或函数,我们也可以找到执行它们的点,获得存储过程或函数的名称,然后再根据名称找到对应的 SQL 文件,再做类似的分析。对于复杂的入口方法,你可能会得到一幅相当大的列表或脑图,它虽然能列出全部内容,但读起来仍然很费劲。这时候我们有两个办法。一是重构复杂的入口方法,抽取出若干小的方法,再以小方法为入口点做分析。二是修改分析工具,直接分析存储过程或函数。如果存储过程或函数过大,也可以进一步拆分。

总结

遗留系统里充满了知识,但通常是加密的,而且我们已经丢失了秘钥。没有测试,我们就无法对遗留系统的预期行为做出清晰的定义。没有一致的结构,我们就必须猜测它是如何设计的、为什么这么设计以及应该如何演进。没有谨慎的命名,我们就必须猜测和推断变量、方法和类的含义,以及每段代码负责的任务。

以假设驱动为指引:如何评价遗留系统的现代化成果?

脱离业务的技术改进都是耍流氓

技术要为业务服务。业务不需要的话,技术升级没有任何意义。

什么是假设驱动?

假设驱动实际上是一种科学的研究方法,在面对一个问题时,我们先要分析问题,然后试着提出一种阐述或者假设,去解释我们的发现。接着就到了实验环节,如果实验结果满足假设,就证明我们的理论是正确的。

《遗留系统现代化》读书笔记(原则篇)_第4张图片

 如果以假设驱动的方式进行开发,我可以在某个方向上快速验证,如果假设不成立,就立即止损,不再追加投资。这样整个过程就显得十分精益了。

在遗留系统中应用假设驱动开发

我们可以将假设驱动开发引入到遗留系统现代化中来,将那些以“As…I want…So that…”或“Given…When…Then…”编写的故事卡和验收条件,改为下面这种形式:

我们相信 < 某个功能 >

将 < 产生某种结果 >

当 < 我们看到某种可度量的信号 > 时,我们就有信心沿着这个方向继续下去

如果只注重产出,我们就会更关注团队都完成了哪些技术改进,考核维度是工作量。这样能快速完成的工作优先级会更高,改进带来的业务价值反而被忽视;但如果注重成效,我们更关注改进如何服务于业务,考核维度变成某项改进,在多大程度上能提高用户效率,并在上线后关注相关指标的变化。

明确目标和度量指标

在以假设驱动的方式推动遗留系统现代化时,首要工作就是确定目标。以下图为例,我们通常可以制定这样四个维度的目标。

《遗留系统现代化》读书笔记(原则篇)_第5张图片

1. 业务敏捷:系统快速响应市场变化和新兴机会的能力,比如一个需求从提出到上线的时间;

2. 运营效率:系统提升价值流效率的能力,比如一个业务从开始办理到办理完成的时间;

3. 客户洞见:系统理解和解释客户数据、行为和反馈的能力,比如前面提到的,客户对于商品视频和直播等特性的敏感程度,我们应该如何去解释;

4. 系统韧性与弹性:云时代对于系统的基本要求。

需要主要的点:

  • 要尽量使用相对的数据,避免使用绝对的数据。
  • 一定要把度量结果用各种图表可视化出来。
  • 以假设驱动为指引的遗留系统现代化,就是说我们所做的所有现代化任务,都应该能够提升这些指标。
  • 推荐阅读:《精益软件度量》

小结

在应用假设驱动开发时,你首先要根据自己的项目制定一些目标,然后再根据目标建立度量体系。这样,所有的技术改进都可以围绕这些指标展开了。

在建立度量指标时要尽量避免绝对的数值,而要尽量用数据的比值。比值更能体现数据的相对性,比绝对的数值更能减少误差。

最后,要记得把数据可视化出来。

以增量演进为手段:为什么历时一年的改造到头来是一场空?

什么是增量演进?

演进式架构的定义:支持跨多个维度的引导性增量变更的架构。

其中,多维度是指技术、数据、安全、运维等不同的看待架构的视角;引导性是指在适应度函数的引导下,向着正确的方向演进架构;而增量变更是指以小步快跑的方式,细粒度地构建和部署软件,同时在一定程度上允许新旧两种实现并行运行。

增量演进是指,以增量的方式,不断向明确的目标前进的过程。

代码的增量演进

在代码现代化方面,我们的主要目标包括三类:修补测试、代码重构、代码分层。

以代码重构为例,向你演示如何实现增量演进。

  • 可以选择先补测试,然后再开始重构。
  • 先把代码复制出来一份,在复制的代码处进行重构。
  • 旧的不变,新的创建。一步切换,旧的再见。

架构的增量演进

绞杀植物模式

  • 第一步,建立开关。要实现增量演进,开关是必不可少的。一方面可以通过开关来控制 A/B 测试,以验证功能不被破坏,另一方面一旦新实现有问题,也能迅速回退到旧实现。
  • 第二步,增量迁移。按迭代逐步将旧模块的功能迁移到新服务中。
  • 第三步,并行运行。对于有一定规模的架构演进,我强烈建议你将开关和旧代码保留一段时间,让新旧代码并行运行几个迭代。
  • 第四步,代码清理。删除旧代码和开关,切记不要忘了这一步。很多遗留系统的架构演进都没有完成这一步,导致很多无用的代码留在系统中。它们除了给人带来迷惑之外没有任何用处。

小结

为什么历时很久的遗留系统改造会以失败而告终呢?一是因为直到最后一刻才上线,失去了持续验证的机会;二是上线后发现有问题,只能硬着头皮热修复,或者整体回滚,缺乏细粒度的回退机制。

而增量演进原则可以有效解决这个问题。它一方面鼓励我们持续交付改造的功能或新的实现,不断在生产环境验证;另一方面拥有细粒度的开关,也使得回退变得十分灵活,一旦发现问题,我们只需要关闭引起问题的那个开关即可。

你可能感兴趣的:(重构,重构,架构,遗留系统)