您好!
欢迎来到京东云开发者社区
登录
首页
博文
课程
大赛
工具
用户中心
开源
首页
博文
课程
大赛
工具
开源
更多
用户中心
开发者社区
>
博文
>
遗留代码处理技巧与案例演示
分享
打开微信扫码分享
点击前往QQ分享
点击前往微博分享
点击复制链接
遗留代码处理技巧与案例演示
自猿其说Tech
2022-10-17
IP归属:未知
79040浏览
### 1 什么是遗留代码 本质是一种技术债务,产生原因一方面是业务原因:如业务本身场景繁多、流程复杂等;另一方面是技术原因:如代码不规范、设计不合理、祖传代码文档注释缺失等。它会影响我们的程序很多方面:如可读性、可修改性、可复用性、可维护性、可测试性等。 ### 2 遗留代码处理过程拆解 划分为梳理->重构/重写->替换/验证三个阶段 ![](//img1.jcloudcs.com/developer.jdcloud.com/ab2bb552-197c-49fc-a3dc-03697d287efd20221017151129.png) #### 2.1 梳理 遗留代码的处理是一种逆向工程,从已有的代码+数据模型+文档倒推出业务模型、交互和规则,在保真的前提下再重新构建代码+数据模型+文档。 我们这里可以参考下DDD领域驱动设计里战略设计部分常用的工具(事件风暴法)来进行这部分梳理工作。 ![](//img1.jcloudcs.com/developer.jdcloud.com/930065a7-b47b-47fc-9030-6f12573b31df20221017151233.png) 事件风暴本质上是一种系统建模的方法,与它处于对等位置的,会有“UML建模”、“事件驱动建模”等。事件风暴跟敏捷开发里的一些理念(如用户故事)的产生背景类似,都是在理性思考无法应对变化频繁且文字难以描述的情况下,通过一些辅助性的提示卡片、视觉手段,辅以相关人员的集中、高频沟通来完成对于业务的准确把握和抽象建模。 **事件风暴的过程:** 1. 通过梳理业务流程,创建相应的领域事件(Event) 2. 补充引发每个领域事件的命令(Command) 3. 通过实体/聚合把命令和事件关联起来 4. 划分领域边界及事件流动线条 5. 识别用户操作所需的关联视图及其角色 **事件风暴的产物:** 1. 领域对象 即实体/聚合。这里的领域对象并非数据库模型, 而是与业务紧密联系的“对象”。因为事件风暴是一种面向对象的建模方式, 而不是面向数据库的建模方式。 2. 领域事件 即对象在某些操作或特点时点下所产生的事件, 这些事件将决定之后多个聚合和限界上下文(BC)之间的通讯方式。 3. 限界上下文 当所有的对象(实体/聚合)被梳理出来后,属于同一种“通用语言”的对象, 则会被归入同一个限界上下文边界内;不属于同一种“通用语言”的对象, 则会被边界给分割开,划入不同的子域或限界上下文。 **梳理结果示例:** ![](//img1.jcloudcs.com/developer.jdcloud.com/89c2e2fc-79c4-480a-8f64-b3e107243fe620221017151411.png) #### 2.2 重构/重写 通过重构/重写对软件要素进行重新组织,使其不改变外部行为的情况下,提升代码的可读性或使其结构更合理。 ![](//img1.jcloudcs.com/developer.jdcloud.com/3afd4893-ed1b-403a-acbb-ab858555600120221017151533.png) 针对不同层次的软件要素要做不同的处理和控制: ![](//img1.jcloudcs.com/developer.jdcloud.com/cd7311cb-b17f-4fef-bb97-7a7e8565b1a920221017151546.png) **并且整个重构/重写过程有些需要遵照的原则:** 1. 单一职责:可以将依赖归拢,统一行为和控制。权责明确,场景明确。 2. 单一原则:消除重复的数据声明、行为;因为单一所以保证了复用,统一标准 ,可装配性。 3. 封装原则:不需要过度关心依赖类内部实现,最好一个.就能调用。 4. 归属原则:上帝的归上帝,凯撒的归凯撒。谁提供的数据更多,归属于谁。 5. 抽象层次:越高层的抽象越稳定,越细节的东西越容易变化。举例:接口应传递职责而非实现细节。 6. 开闭原则:对修改关闭,对扩展开放。 7. kiss原则: 好理解,好维护。 8. 清晰原则:只读小部分代码就可以知道怎么改逻辑,做扩展。而不是要通读所有代码,才能理清。 其中有两点落地细节我们具体分析下: 1. 业务逻辑的处理 业务代码和技术代码解耦 主流程代码和附加流程代码解耦 长链路的拆解编排 1. 关注点的分离 双向依赖:上下文之间缺少一层未被澄清的上下文,或者两个上下文其实可被合为一个; 循环依赖:任何一个上下文发生变更,依赖链条上的上下文均需要改变; 过深的依赖:自身依赖的信息不能直接从依赖者获取到,需要通过依赖者从其依赖的上下文获取并传递,依赖链路过长,依赖链条上的任何一个上下文发生变更,其链条后的任何一个上下文均可能需要改变; #### 2.3 替换验证 大概分为以下几个要点: 1. 领会意图,抽取用例,增加可复测性 2. 增加可监测性 3. 分成小块,逐步替换 4. 试点、看到成效 可借助过程管理工具如PDCA法进行管理 ![](//img1.jcloudcs.com/developer.jdcloud.com/00ba7777-53f5-48c1-9641-8284d086c8f020221017152623.png) ### 3 案例演示 #### 3.1 案例1:针对强耦合的实现做重构 **原始需求:**案例为一个转账服务,用户可以通过银行网页转账给另一个账号,支持跨币种转账。同时因为监管和对账需求,需要记录本次转账活动。 **原始架构:**是一个传统的三层分层结构:UI层、业务层、和基础设施层。上层对于下层有直接的依赖关系,导致耦合度过高。在业务层中对于下层的基础设施有强依赖,耦合度高。我们需要对这张图上的每个节点做抽象和整理,来降低对外部依赖的耦合度。 ![](//img1.jcloudcs.com/developer.jdcloud.com/aabe5a80-f355-436b-9783-f5bcf5e5c3e020221017152854.png) 重构关键设计点: ![](//img1.jcloudcs.com/developer.jdcloud.com/e9d90d22-6b88-4f97-a629-b2ee85c3c68b20221017152906.png) 重构后代码特征: 业务逻辑清晰,数据存储和业务逻辑完全分隔。 Entity、Domain Primitive、Domain Service都是独立的对象,没有任何外部依赖,但是却包含了所有核心业务逻辑,可以单独完整测试。 原有的转账服务不再包括任何计算逻辑,仅仅作为组件编排,所有逻辑均delegate到其他组件。 #### 3.2 案例2:提高老代码的复用性 **原始需求:**现有几个策略实现类,被很多代码使用。现在需要根据不同的业务方在每个策略执行前做不同的前置逻辑处理。 **解法分析:**尽量避免把逻辑耦合到已有的实现类中。引入外部类进行控制反转。这里我们使用访问者模式。 访问者模式把数据结构和作用于结构上的操作解耦合,使得操作集合可相对自由地演化。访问者模式适用于数据结构相对稳定算法又易变化的系统。因为访问者模式使得算法操作增加变得容易。若系统数据结构对象易于变化,经常有新的数据对象增加进来,则不适合使用访问者模式。访问者模式的优点是增加操作很容易,因为增加操作意味着增加新的访问者。访问者模式将有关行为集中到一个访问者对象中,其改变不影响系统数据结构。其缺点就是增加新的数据结构很困难。 ![](//img1.jcloudcs.com/developer.jdcloud.com/7e8471e3-55d0-4ea0-a35c-a1422c22edfc20221017153145.png) 具体实现: ![](//img1.jcloudcs.com/developer.jdcloud.com/5c919369-9cc5-4789-9c21-ef96cc61c6bf20221017153208.png) ![](//img1.jcloudcs.com/developer.jdcloud.com/fe260e94-8220-49f6-a31d-7b95ac45e07020221017153216.png) 重构后代码特征: 可以通过访问者对老代码逻辑进行编排,将修改外置,减少对老逻辑的影响 通过java8默认接口实现提供默认访问行为,避免大量策略子类的感知,只需要需要提供自己实现行为的子类对默认实现进行覆写 ### 4 总结 遗留代码的处理能力一方面是对技术的要求,另一方面也是对业务掌握的挑战。希望我们可以跨越荆棘、穿过迷雾,顺利到达成功的彼岸! ------------ ###### 自猿其说Tech-JDL京东物流技术与数据智能部 ###### 作者:冯鸿儒
原创文章,需联系作者,授权转载
上一篇:Dive into TensorFlow系列(3)- 揭开Tensor的神秘面纱
下一篇:测试进阶之路—新手关于测试碎碎念篇
自猿其说Tech
文章数
426
阅读量
2149964
作者其他文章
01
深入JDK中的Optional
本文将从Optional所解决的问题开始,逐层解剖,由浅入深,文中会出现Optioanl方法之间的对比,实践,误用情况分析,优缺点等。与大家一起,对这项Java8中的新特性,进行理解和深入。
01
Taro小程序跨端开发入门实战
为了让小程序开发更简单,更高效,我们采用 Taro 作为首选框架,我们将使用 Taro 的实践经验整理了出来,主要内容围绕着什么是 Taro,为什么用 Taro,以及 Taro 如何使用(正确使用的姿势),还有 Taro 背后的一些设计思想来进行展开,让大家能够对 Taro 有个完整的认识。
01
Flutter For Web实践
Flutter For Web 已经发布一年多时间,它的发布意味着我们可以真正地使用一套代码、一套资源部署整个大前端系统(包括:iOS、Android、Web)。渠道研发组经过一段时间的探索,使用Flutter For Web技术开发了移动端可视化编程平台—Flutter乐高,在这里希望和大家分享下使用Flutter For Web实践过程和踩坑实践
01
配运基础数据缓存瘦身实践
在基础数据的常规能力当中,数据的存取是最基础也是最重要的能力,为了整体提高数据的读取能力,缓存技术在基础数据的场景中得到了广泛的使用,下面会重点展示一下配运组近期针对数据缓存做的瘦身实践。
自猿其说Tech
文章数
426
阅读量
2149964
作者其他文章
01
深入JDK中的Optional
01
Taro小程序跨端开发入门实战
01
Flutter For Web实践
01
配运基础数据缓存瘦身实践
添加企业微信
获取1V1专业服务
扫码关注
京东云开发者公众号