Linux 之父出席、干货分享、圆桌讨论,精彩尽在 OpenCloudOS 社区开放日,报名戳 了解详情
写点什么

如何在遗留代码基础上开发

  • 2013 年 3 月 19 日
  • 本文字数:2119 字

    阅读完需:约 7 分钟

对于大多数开发者来说,在遗留代码基础上开发是日常工作的一部分,毕竟从头开始创建全新系统的机会不是很多。架构师、《漫谈设计模式》作者刘济华结合自身的实际经历分享了如何在遗留代码基础上开发的经验。

刘济华首先指出,大多数系统是构建在之前的遗留系统之上的,在开始,很难把遗留系统直接丢弃,特别是一些业务逻辑非常复杂的金融电信系统。 这些代码往往有如下特点:

  • 旧的编程语言开发低效。
  • 代码冗繁,质量差。
  • 添加新的功能和修改错误(Bugs)的周期时间长而痛苦。
  • 这些代码没有单元测试,甚至没有功能测试、冒烟测试、回归测试。
  • 无法交接这些代码,因为写代码的这些人很多已经离职。
  • 维护这些代码代价高,大家心惊肉跳,特别是系统遇见特殊情况(节假日,高峰访问期等),无法安宁。

但是这些代码能够完成当时的功能,直接抛弃这些代码,重新开发将会耗费很大的资源,且不一定成功,如果新的需求不断变化,往往没有时间来重新开发这些代码。而这些遗留代码的功能没有完善的文档说明,甚至没有。 在此现状下,如何改善这些代码,将是考验程序员和一个团队的智慧。

接着,刘济华分析了对于遗留代码取舍的亲身经历。

  • 具有性能瓶颈的遗留系统——曾经遇到过一个应用服务,是 C 语言写的,周围其他系统都是采用 Java 开发,与此系统的交互都是采用非标准的协议完成,而且此系统处于比较核心的位置,但是维护非常复杂,不稳定,访问压力大是经常宕机,无法水平扩展,只能提高硬件设备水平等方式考虑。
    在原有协议基础上开发,使其具有水平扩展能力,代价和开发一套标准协议的实现没有任何区别,往往会带了协议不够完善所产生的问题。于是,我们为其开发新的标准协议,WS,MQ 等等,然后在标准协议上负载均衡实施水平扩展,非常方便。
    随着后来的发展,此遗留代码也慢慢被新开发系统取代,期间经历了新系统和旧系统同时存在,此时新系统未完全具有旧系统的全部功能,这部分功能还是使用旧系统完成,只不过在原有均衡负载层多了层查找和分配的,后来到旧系统完全取代。此过渡还算平顺。
  • 功能性改造型系统——大多数就是这种系统,保留的话,代码极其复杂,维护麻烦,丢弃的话,无法一夜之间写出新的系统。曾经接手了一个开发失败的项目,包括代码和文档都未完善,如果重新来过,终究不划算,后来在此系统上进行改造,特别是花了大量时间写单元测试,保证代码测试覆盖率极高,这样一边熟悉代码,一边重构代码,系统的健壮性发生根本改变,前提是有时间。这只是特例。很多时候遇见的系统,同样测试代码很少,在添加新的功能和修复错误(Bugs)时,为这些能够接触到的代码完善测试,新代码必须测试覆盖率必须很高,经过 4 个月,,此系统代码覆盖率已经达到 50% 以上。以后的迭代开发越来越快。

那么如何在在遗留代码上编程呢?刘济华觉得首先要找到代码修改点:

遗留系统代码往往测试少,或者没有,导致软件开发者对软件发布没有信心。但是为所有的遗留代码写单元测试,初始代价非常高,在添加一个很小的功能时,并没有时间大动干戈。

如何找切入点呢? 刘济华总结了几种情况:

  • 修改一处代码即可,这个时候非常简单,修改代码处即为切入点,找到这处修改即可,为此处代码写完善的单元测试代码,特别是对于输入条件和测试条件尽量能够完整测试。
  • 修改多处代码,位置分散,并且修改代码如果有多种方案,我们找出最少修改代码的地方,而不是最佳的修改方式,很多时候,此时最佳的代码修改会修改很多代码,导致测试代码无法一下子完善,另外,此时认为的最佳方案随着时间的推移,或许又是糟糕的代码,所以没有必要花费更多的精力在上面,当然也可以选择比较中庸的方式。

在修改时需要一些技巧,其中包括:

  • 找测试方便、改动较小的方式来修改遗留代码。
  • 重构在一个类中那些重复的方法,并且保证其健壮性。
  • 为依赖的具体类提取新的接口,并使用注入依赖技术,使得测试更加容易,不管是使用 Mock tool 还是自己编写 Mock 对象,都会非常容易测试。
  • 尽量使测试的范围缩小在受修改影响的类中,对类中的改动进行全面测试。保证每处修改完全测试,保证测试类减少。
  • 类之间交互的代码重构,如果这些交互仅在修改的代码之中,只要保证修改的代码完全测试即可。而对于那些可能影响此时其他不需要进行修改代码的类,可以先放下,为其创建新的方法,在此次修改和以后修改中,使用和重构新的方法。对于老的方法,等到以后代码覆盖率提高,能够覆盖所有此类交互方法的代码时,重构此方法,这是你会发现,修改很简单,并且如果修改错误,或者不能处理极端的逻辑,也会和容易找出问题所在。
  • 努力汲取业务逻辑知识。
  • 《修改代码的艺术》(Michael Feathers 著)建议找到切入点(Inflection Point),往往我们找的点很多,每一次修改都可能不一样,为此花很多代价找寻,还不如直接进入修改,找出最佳的修改方式避免代码过度重构和修改,减少影响,这才是有有实践价值和有意义的。

如何保证质量呢?刘济华建议:

  • 尽可能让一切自动化——单元测试自动化是最基本要求,尽可能让一切测试变得自动化,不管是单元测试,还是功能测试,还是压力测试、冒烟测试、回归测试。发布自动化也是非常重要的。
  • 为项目加入冒烟测试和回归测试。逐渐保证代码质量。
  • 坚持可控变化、逐渐渗透的原则,保持系统稳步的朝健壮的方向进行。
2013 年 3 月 19 日 01:023375
用户头像

发布了 501 篇内容, 共 227.7 次阅读, 收获喜欢 51 次。

关注

评论

发布
暂无评论
发现更多内容

都说数仓是面向主题建设的,那数仓的主题和主题域又应该怎么划分呢?

白程序员的自习室

数仓 7月日更 数仓主题 主题域 数仓建设

使用 Open Policy Agent 实现可信镜像仓库检查

张晓辉

Kubernetes 安全 OPA

为什么搞一个副业项目如此之难?

张理查

详聊微服务观测|从监控到可观测性,我们最终要走向哪里?

尔达Erda

开源 微服务 云原生 APM PaaS

架构实战营模块8作业

Geek_649372

架构实战营

PowerShell 哈希表

耳东@Erdong

PowerShell 7月日更

external-attacher源码分析(2)-核心处理逻辑分析

良凯尔

Kubernetes 源码分析 Ceph CSI Kubernetes Plugin

免费分享Java Web 开发的优秀图书

Java入门到架构

Java Java书籍推荐

学习总结 IoT方向的小项目

万里无云万里天

学习 IoT

数据仓库的基本要求

奔向架构师

数据仓库 数据架构 7月日更

🏆「作者推荐」【JVM性能分析】精心准备了一套JVM分析工具的锦囊(上部)

浩宇天尚

JVM 性能分析 jvm调优 7月日更

phpExcel:Excel数据导入导出最佳实战

devpoint

php Excel thinkphp 7月日更

Redisson 分布式锁源码 08:MultiLock 加锁与锁释放

程序员小航

Java 源码 分布式锁 redisson redison

推荐系统的价值观(三十二)

数据与智能

价值观 推荐系统

吃药吗?AI造的!

脑极体

Linux之find xargs

入门小站

Linux

在线ASCII艺术字生成工具,SpringBoot banner生成工具

入门小站

工具

【Flutter 专题】91图解 Dart 单线程实现异步处理之 Future (二)

阿策小和尚

Flutter 小菜 0 基础学习 Flutter Android 小菜鸟 7月日更

面对大规模 K8s 集群,这款诊断利器必须要“粉一波”!

尔达Erda

开源 云原生 operator PaaS kubernete

禾木之变:2021我们该如何持续拥抱AI?

脑极体

解读区块链在制药和物流管理中具备的优势

CECBC

模块一作业

君子意如何

「架构师训练营第 1 期」

你的直观感受有可能是错的

石云升

学习 认知偏差 7月日更

数字政府建设如火如荼 区块链保证数据真实安全

CECBC

利用 Vector 从日志创建指标来提高系统的可观测性

哈德韦

日志 可观测性 Prometheus SRE vector

区块链技术在“三资”监管领域的应用

CECBC

设计消息队列存储消息数据的MySQL表格

Vincent

架构训练营

jTDS 驱动导致 cpu 100%

顾五木

cpu占用100% 线上程序问题

5分钟速读之Rust权威指南(三十九)unsafe

码生笔谈

rust

【得物技术】常用注册中心原理及比较

得物技术

zookeeper nacos Consul Eureka 注册中心

幸福来敲门

卢卡多多

幸福 7月日更

GPU容器虚拟化:用户态和内核态的技术和实践详解

GPU容器虚拟化:用户态和内核态的技术和实践详解

如何在遗留代码基础上开发_DevOps_崔康_InfoQ精选文章