65.9K
CodeProject 正在变化。 阅读更多。
Home

维护编程的艺术

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.81/5 (85投票s)

2004年12月14日

10分钟阅读

viewsIcon

172296

一些使维护编程更有趣的小贴士。

引言

我曾看过和读过无数关于新开发的书籍和文章,内容涵盖设计和架构、编码以及项目规划和管理。但对于那些谦逊且被忽视的维护编程,情况并非如此。在软件生命周期的研究中,维护经常被提及,但实际的设计和编码技术通常是在积极开发(而不是维护)的背景下教授的。

在这里,我甚至不想尝试定义维护编程,也不想引用别人的定义。相反,我将列出一些已维护软件相对于积极开发软件的特征。

  • 它已被部署和使用。
  • 原始开发人员可能已离开公司或转到其他任务。参与维护产品的人员比开发产品的人员少。
  • 对于已维护软件的期望通常较低。维护通常包括修复用户报告的错误,并添加一些功能,但它不是“旗舰”。
  • 已维护代码通常是用遗留技术甚至不受支持的技术开发的。代码质量通常会因最后一刻的错误修复和其他技巧而下降。

维护编程的良好实践

我在这里提供的小贴士是我个人经验的结果。您可能会发现它们在您的情况下并不适用,或者更可能的是,其中一些适用,而另一些则不适用。如果您有任何其他建议,请在文章论坛中发布。

1. 喜欢上它

如何有人会喜欢维护编程?开发人员梦想成为团队中的首席架构师,而当他们最终维护现有软件时,这几乎就像一种惩罚。但不必如此:维护编程有其自身的挑战,需要大量的创造力、适应性、耐心、纪律和良好的沟通。它对您的职业生涯也有好处:您的简历中有“架构了 24/7 企业级多层应用程序”这样的华丽条目看起来不错,但雇主实际上看重的是解决问题的人;维护编程是展示您解决问题能力的好机会。

2. 熟悉您所维护软件的功能

了解您所维护软件的功能至关重要。阅读现有文档,并确保亲身体验。如果您有 QA 部门,尝试找出测试计划并进行演练。找出软件在实际中的使用方式,并确保您了解最常见的用途场景。有时用户会向您请求已经存在的功能,只是他们不知道。在其他情况下,会有一些方便的变通方法。如果您是您所维护软件的重度用户,您在调试器中花费的时间可能会更少。

3. 熟悉您所维护软件的架构

您期望继承详细且最新的设计文档,包括需求、功能规范、高级和低级设计,以及注释良好的代码,对吗?实际上,这种情况发生的几率接近于零。更有可能的是,您获得的文档很少,甚至没有,即使有,也可能已过时。代码,或其中部分,可能已注释,但您无法确定即使是注释也是最新的;有时它们实际上可能具有欺骗性,如果代码在此期间被更改了。

查看代码;尝试理解类、模块和组件的角色。使用调试器:逐步执行不同的使用场景,并查看当代码的不同部分执行时会发生什么。务必记录您的发现并以某种形式组织它们;它可以是 UML 图等正式方法,也可以是非正式但易于理解的方法。将熟悉架构视为一个持续的过程,而不是一次性的事情。当您开始修复错误和添加功能时,您将有机会更深入地了解系统;在此阶段也要确保记录您的发现。

4. 与用户沟通

我怎么强调都不为过这一点的重要性。许多软件开发人员是内向的人,他们宁愿与技术打交道而不是与人打交道。然而,软件是为人们使用的而编写的,在已维护软件的情况下,我们已经有了用户。找出他们如何使用软件、为什么使用它、他们试图解决什么问题、需要什么功能,这一点至关重要。要找出这些,不要等他们来找您;主动出击,去接触他们。尝试建立简单有效的提交错误报告和功能增强请求的流程。当他们报告问题时,立即回复他们,即使您此时没有解决方案——让他们知道您正在处理此事,而不是忽略他们。让他们了解他们问题的状态。最后,要诚实;如果您因为任何原因无法满足他们的请求,请告知他们。

5. 如果可能,与原始开发人员沟通

如果您够幸运,一些原始开发人员仍在公司。当然,他们已经向前看,不想再管您正在维护的这个糟糕的老软件了,但他们可以为您提供巨大的帮助,并节省您大量时间。不要指望他们为您编写实际代码,但他们可以给您一个关于如何完成某事的想法,向您解释为什么某个东西会以某种方式工作,并为您提供许多有用的提示。同样,与他们打交道需要许多开发人员缺乏的“人际交往能力”,但这并非我们学不会的东西。

6. 保留更改历史记录

有多种不同的且不相互排斥的方法来保留更改历史记录。最显而易见的事情是评论您源代码控制系统中的每一次提交(我甚至不考虑您不使用源代码控制系统的可能性)。有些人喜欢将更改列表放在每个文件的顶部。将更改集中在一个电子表格中可能也很方便。无论您采取哪种方法,都要认真对待。准确的更改历史记录对于成功的维护是无价的,即使您之前的没有人处理过它,而您只得到了一部分更改列表。

7. 保持谨慎

在维护工作中,您会多次对某个模块中的现有代码感到沮丧,并想将其抛弃并从头重写。但在实际这样做之前,请问自己一些问题:

  • 这将如何使您的组织及其客户受益?某些代码不好看,或者在您看来不好看,这本身并不是重写的理由。如果客户想要一个无法添加到现有代码中的功能,这可能是一个考虑重写的理由。
  • 您确定您理解这段代码的作用以及它的工作原理吗?
  • 您确定您理解它如何与其他系统部分交互,以及哪些模块和功能依赖于您想重写的代码吗?
  • 您确定您能做得更好吗?也许您会遇到与原始开发人员相同的问题,并且做得一样糟甚至更糟。

事实是,无论何时我们对现有代码进行更改,无论更改多么微不足道,都有引入错误的风险。因此,我们希望在可行的情况下尽可能保持谨慎。当请求新功能时,如果可能,我们希望将其实现为一个单独的模块,并保持旧代码不变。如果它没有坏,就不要修复它。如果它坏了,宁愿修复它而不是从头重写。尽量使更改局部化——您不希望发现您改进了系统的某一部分,却破坏了另一部分。

避免重构。虽然它在积极开发过程中可能是一项有用的技术,但在维护阶段,它可能会给您带来麻烦。即使您没有通过重构破坏任何东西,您也会弄乱您的更改历史记录,并弄乱您源代码控制系统中的版本差异(您确实有一个源代码控制系统,对吧?)。

同样,当您更改代码或添加新功能时,尽量立即以正确的方式完成。我曾多次看到人们说“我们现在快速写个补丁来赶上截止日期,以后再好好重写”。嗯,由于各种原因,“以后”通常永远不会到来。如果可以,请正确地做;如果不行,请对自己诚实,不要以“以后”为借口。

8. 每次更改后进行测试

也许在接手维护软件后,您需要做的第一个编码任务是为其编写一套全面的回归测试套件;除非您已经继承了一个,但总的来说,您不太幸运。诚然,自动化测试不能保证代码没有错误,但这是逃避它们的糟糕借口;它们不会发现所有错误,但它们将帮助您发现许多错误,并让您确信在进行更改后,您所维护软件的核心功能没有被破坏。一个好习惯是,对于您收到的每一个错误报告,编写一个测试用例来重现它。这样,您就会知道在修复其他东西时是否重新引入了错误。

有时,根据被维护的软件,在每次要签入源代码控制系统(您确实有,对吧?)的小更改后运行整个回归测试套件可能需要太长时间。在这种情况下,采取回归测试的一个子集并进行“冒烟测试”可能很有用,它只覆盖回归测试套件中的一部分测试用例。您会在每次更改后运行此冒烟测试,并在夜间或周末运行回归测试。

9. 采用现有的代码约定,即使您不喜欢

人们对代码约定非常执着,总的来说,很难让人改变他们对使用哪种编码约定的看法。即使是那些有作者建议的编码约定的语言(如 Java、Visual Basic 和 C#),开发人员仍然为它们争论不休。对于作者将约定留给开发人员的语言(C、C++、Perl),选择约定的问题很快就会变成一场战争。

我知道我不会说服任何人,但尽量坚持您在维护的代码中存在的任何约定。即使整个系统没有统一的约定,但很可能约定在模块级别至少是统一的,因为在大多数情况下,一个人开发一个模块。在最坏的情况下,原始开发人员以外的其他人已经修改了代码并使用了其他约定,因此您将不得不处理一堆糟糕的约定。即使在这种情况下,也请采用现有的约定之一,而不是引入另一个。

结论

维护编程有其自身的挑战,这些挑战需要以一种有纪律的方式来解决,就像积极开发一样。在本文中,我介绍了一些我在工作中发现很有用的实践;这绝不是要写一本关于维护编程艺术的权威指南。

© . All rights reserved.