在遗留代码上开发(Development on legacy code)
遗留代码
笔者从开发伊始到现在,大多数系统是构建在之前的遗留系统之上的,在开始,很难把遗留系统直接丢弃,特别是一些业务逻辑非常复杂的金融电信系统。 这些代码往往有如下特点:
1.旧的编程语言开发低效。
2.代码冗繁,质量差。
3.添加新的功能和修改错误(Bugs)的周期时间长而痛苦。
4.这些代码没有单元测试,甚至没有功能测试,冒烟测试,回归测试。
5.无法交接这些代码,因为写代码的这些人很多已经离职。
6.维护这些代码代价高,大家心惊肉跳,特别是系统遇见特殊情况(节假日,高峰访问期等),无法安宁。
7.但是这些代码能够完成当时的功能,直接抛弃这些代码,重新开发将会耗费很大的资源,且不一定成功,如果新的需求不断变化,往往没有时间来重新开发这些代码。而这些遗留代码的功能没有完善的文档说明,甚至没有。 在此现状下,如何改善这些代码,将是考验程序员和一个团队的智慧。
开发
笔者在多年的遗留系统的开发硝烟中,也尝尽许多痛苦,技术层面的,政治层面的等等。然而,没有这些磨练,也就不会有任何收获,废话少说,看看现在我们如何改造这些遗留系统。
保留系统还是取代?
1.具有性能瓶颈的遗留系统:
曾经遇到过一个应用服务,是C语言写的,周围其他系统都是采用Java开发,与此系统的交互都是采用非标准的协议完成,而且此系统处于比较核心的位置,但是维护非常复杂,不稳定,访问压力大是经常宕机,无法水平扩展,只能提高硬件设备水平等方式考虑。
在原有协议基础上开发,使其具有水平扩展能力,代价和开发一套标准协议的实现没有任何区别,往往会带了协议不够完善所产生的问题。于是,我们为其开发新的标准协议,WS,MQ等等,然后在标准协议上负载均衡实施水平扩展,非常方便。
随着后来的发展,此遗留代码也慢慢被新开发系统取代,期间经历了新系统和旧系统同时存在,此时新系统未完全具有旧系统的全部功能,这部分功能还是使用旧系统完成,只不过在原有均衡负载层多了层查找和分配的,后来到旧系统完全取代。此过度还算平顺。
2.功能性改造型系统:大多数就是这种系统,保留的话,代码及其复杂,维护麻烦,丢弃的话,无法一夜之间写出新的系统。
曾经接手了一个开发失败的项目,包括代码和文档都未完善,如果重新来过,终究不划算,后来在此系统山进行改造,特别是花了大量时间写单元测试,保证代码测试覆盖率极高,这样一边熟悉代码,一边重构代码,系统的健壮性发生根本改变,前提是有时间。这只是特例。
很多时候遇见的系统,同样测试代码很少,在添加新的功能和修复错误(Bugs)时,为这些能够接触到的代码完善测试,新代码必须测试覆盖率必须很高,经过4个月,,此系统代码覆盖率已经达到50%以上。以后的迭代开发越来越快。
以下将这种讲解这种方式的开发过程。
在遗留代码上编程
找代码修改点
遗留系统代码往往测试少,或者没有,导致软件开发者对软件发布没有信心。但是为所有的遗留代码写单元测试,初始代价非常高,在添加一个很小的功能时,并没有时间大动干戈。
如何找切入点呢?
为了新的改动,我们总能找到应该修改的代码在哪里,不外乎以下几种情况:
1.修改一处代码即可,这个时候非常简单,修改代码处即为切入点,找到这处修改即可,为此处代码写完善的单元测试代码,特别是对于输入条件和测试条件尽量能够完整测试。
2.修改多处代码,位置分散,并且修改大妈如果有多种方案,我们找出最少修改代码的地方,而不是最佳的修改方式,很多时候,此时最佳的代码修改会修改很多代码,导致测试代码无法一下子完善,另外,此时认为的最佳方案随着时间的推移,或许又是糟糕的代码,所以没有必要花费更多的精力在上面,当然也可以选择比较中庸的方式。
技巧
1.找测试方便,改动较小的方式来修改遗留代码。
2.重构在一个类中那些重复的方法,并且保证其健壮性。
3.为依赖的具体类提取新的接口,并使用注射依赖技术,使得测试更加容易,不管是使用Mock tool还是自己编写Mock对象,都会非常容易测试。
比如,
class Manager{ ... public void kickOff(){ ... DoSomething doSomething = new DoSomething(...); doSomething.doSomething(objects); } ... }
可修改为:
class Manager{ ... DoSomething doSomething; public void setAction(Action doSomething){ this.doSomething = doSomething; } public void kickOff(){ ... doSomething.doSomething(objects); } ... } interface Action { void doSomething(List marks); }
为DoSomething提供了接口Action,采用诸如依赖,mock这个DoSomething这个类,测试kickOff()方法。
4.尽量使测试的范围缩小在受修改影响的类中,对类中的改动进行全面测试。保证每处修改完全测试,保证测试类减少。
5.类之间交互的代码重构,如果这些交互仅在修改的代码之中,只要保证修改的代码完全测试即可。而对于那些可能影响此时其他不需要进行修改代码的类,可以先放下,为其创建新的方法,在此次修改和以后修改中,使用和重构新的方法。对于老的方法,等到以后代码覆盖率提高,能够覆盖所有此类交互方法的代码时,重构此方法,这是你会发现,修改很简单,并且如果修改错误,或者不能处理极端的逻辑,也会和容易找出问题所在。
6.努力汲取业务逻辑知识。
7.《修改代码的艺术》(Michael Feathers 著)建议找到切入点(Inflection Point),往往我们找的点很多,每一次修改都可能不一样,为此花很多代价找寻,还不如直接进入修改,找出最佳的修改方式避免代码过度重构和修改,减少影响,这才是有有实践价值和有意义的。
质量保证
总之,和遗留代码打交道时,为了提高发布信心和效率,速度和质量是我们的追求。
1.尽可能让一切自动化:
单元测试自动化是最基本要求,尽可能让一切测试变得自动化,不管是单元测试,还是功能测试,还是压力测试,冒烟测试,回归测试。
发布自动化也是非常重要的。
2.为项目加入冒烟测试和回归测试。逐渐保证代码质量。
3.坚持可控变化,逐渐渗透的原则,保持系统稳步得朝健壮的方向进行。
关于重构推荐的书籍:
《重构:改善既有代码的设计》Martine Fowler著
《重构与模式》:Joshua Kerievsky著
《修改代码的艺术》: Michael Feathers 著
参考:
《修改代码的艺术》: Michael Feathers 著
本文作者:
现就任某公司金融软件高级资深技术架构师,著有《漫谈设计模式》一书(清华大学出版社出版)。
相关推荐
《修改代码艺术(Working Effectively with Legacy Code)》是一本专为软件开发人员设计的经典书籍,专注于如何在已有代码库中进行高效、安全的修改。这本书由Michael Feathers撰写,旨在帮助开发者面对和改善那些缺乏...
世界级计算机专家...防止引入新的问题包含Java、C++、C和C#的示例,其中介绍的大多数技术适用于其他任何语言或平台,精确地确定要在哪些地方修改代码处理非面向对象的遗留代码处理看起来没有任何结构的应用程序。
《修改代码的艺术——Working Effectively with Legacy Code》是软件开发领域一本极其重要的著作,由Michael Feathers撰写。这本书深入探讨了如何在已有代码库(通常称为遗留代码)中进行有效的修改和维护工作,以...
If the answer to any of these questions is no, you have legacy code, and it is draining time and money away from your development efforts. In this book, Michael Feathers offers start-to-finish ...
《Working Effectively with Legacy Code》是软件开发领域中一本经典的著作,由Michael Feathers撰写,主要探讨如何在已有大量遗留代码的基础上进行有效的工作和改进。这本书对于任何在维护旧项目或处理遗留系统的...
Working Effectively With Legacy Code
在软件开发领域,面对遗留代码(Legacy Code)是不可避免的挑战之一。本文将深入探讨如何有效地处理遗留代码,帮助开发者提高工作效率并降低风险。首先,我们需要明确什么是遗留代码。 **遗留代码定义**:通常来说...
《Working Effectively with Legacy Code》是一本由Michael Feathers所著的经典书籍,专注于如何在已有大量遗留代码的项目中进行高效、安全的修改和维护。这本书对于任何在IT行业中处理旧代码库或需要升级现有系统的...
- **思维转变**:鼓励读者进行深层次的思考,探索如何在现有基础上改进软件开发流程。 ##### 2.3 高效迭代交付 - **核心理念**:强调了频繁迭代交付对于提高软件质量和满足客户需求的重要性。 - **实践方法**:...
[Apress] 软件开发 降魔录 (遗留代码调试优化手册) (英文版) [Apress] Software Exorcism (E-Book) ☆ 图书概要:☆ Software Exorcism: A Handbook for Debugging and Optimizing Legacy Code takes an ...
遗留代码是指那些没有测试或难以测试的旧代码,它通常缺乏良好的设计和文档,导致开发者难以进行进一步的开发或维护。这本书提供了一整套方法论和实践技巧,帮助开发者逐步提高遗留代码的质量。 书中首先定义了什么...
"legacy-code-master"这个文件名可能表示这是一个关于管理和理解遗留代码的项目或资源库,可能是为了整理、重构或迁移这些代码而创建的。 处理遗留代码需要一系列策略。首先,进行代码审查是必要的,以理解代码的...
在当今快速发展的软件行业中,遗留代码(Legacy Code)成为了一个无法回避的问题。遗留代码通常指的是那些未附带完整测试套件、随着时间推移逐渐变得难以维护和扩展的代码。这种代码不仅降低了软件项目的整体质量,...
"Legacy"在软件开发领域中,通常指的是那些没有文档、质量参差不齐、结构复杂且难以理解的旧代码库。这些代码可能随着时间推移,原有的开发者离职或者业务需求变化而变得难以维护。然而,遗留代码是许多组织的核心...
本书是一部里程碑式的著作,针对大型的、无测试的遗留代码基,提供了从头到尾的方案,让你能够更有效地应付它们,将你的遗留代码基改善得具有更高性能、更多功能、更好的可靠性和可控性。本书还包括了一组共24项解...
For most scenarios, such as development on Windows and .NET Core RC2 on OS X and Linux, you should use the latest C# extension for Visual Studio Code. However, support for Unity and Xamarin, and other...