有效使用旧版守则的关键点是什么?[关闭]


133

我看过推荐过几次《有效使用旧版代码》的书。本书的重点是什么?

除了添加单元/集成测试然后进行重构之外,处理遗留代码还有更多的事情吗?



2
当然,重点是添加测试,然后进行重构。这本书主要是关于如何设法测试令人费解的代码,在这一点上有很多令人大开眼界的事情。我们只说羽毛不带任何囚犯!
Kilian Foth

9
也许您应该只读这本书
HLGEM

尼斯的审查在这里:andreaangella.com/2014/03/...
rohancragg

Answers:


157

遗留代码的关键问题是它没有测试。因此,您需要添加一些(然后添加更多...)。

正如@mattnz指出的那样,这本身将需要大量工作。但是,遗留代码的特殊问题是它从未设计为可测试的。因此,通常情况下,这是一团乱七八糟的意大利面条代码,很难或根本不可能隔离要进行单元测试的小零件。因此,在进行单元测试之前,您需要重构代码以使其更具可测试性。

但是,为了安全地进行重构,您必须进行单元测试,以确保所做的更改没有破坏任何东西。这是遗留代码的第22条。

这本书教您如何通过对代码进行绝对最小,最安全的更改来实现这一目标,以启用第一个单元测试。这些并不是为了使设计更好,而只是为了进行单元测试。实际上,有时它们确实会使设计更难看或更复杂。但是,它们允许您编写测试-一旦有了单元测试,就可以自由地改进设计。

有很多技巧可以使代码可测试-有些很明显,有些根本没有。如果不阅读本书,有一些我从未想过的方法。但是更重要的是,Feathers解释使代码单元可测试的确切原因。您需要削减依赖性并在代码中引入障碍,但这有两个明显的原因:

  • 感应 -为了检查和验证执行一段代码的效果,并且
  • 分离 -首先将特定的代码放入测试工具。

安全地削减依赖关系可能很棘手。引入接口,模拟和依赖注入是很干净,很不错的目标,但此时不一定要安全。因此,有时我们不得不求助于被测类的子类,以覆盖某些方法,该方法通常会例如启动向数据库的直接请求。其他时候,我们甚至可能需要在测试环境中用伪造的依赖类/ jar替换依赖类/ jar。

对我来说,羽毛带来的最重要的概念是接缝接缝是代码中可以更改程序行为而无需修改代码本身的地方。在代码中建立接缝可以分离被测代码段,但是即使在很难或不可能直接执行时(例如,由于调用在另一个对象或子系统中进行更改),也可以使您感知被测代码的行为。 ,其状态无法直接从测试方法中查询)。

这些知识使您可以注意到最讨厌的代码堆中的可测试性种子,并找到到达那里的最小,破坏性最小,最安全的更改。换句话说,为了避免“明显”的重构具有破译密码没有你注意到的风险-因为你不具备单元测试来检测。


5
请注意,当以上答案说“单元测试”时,实际上是“自动测试”。对于旧版应用程序,实际上,最初有用的自动化测试中有很大一部分实际上是集成测试(测试逻辑执行较大部分的整体代码,并可能由于许多不同位置的缺陷而导致失败),而不是真正的单元。测试(旨在仅分析一个模块并分别执行更小的代码部分)。
Lutz Prechelt

99

获得有效使用旧版代码的关键点的快速方法


3
该Hanselminutes页面上的MP3链接断开,但对一个hanselminutes.com/165/...不是- s3.amazonaws.com/hanselminutes/hanselminutes_0165.mp3
彼得·莫滕森

感谢rosston修复了PDF链接。看起来objectmentor.com已经消失了-也许“鲍勃叔叔”倒闭了吗?
MarkJ

我不确定对象导师怎么了,但是这些天鲍勃叔叔为第七光工作。
Jules

40

我在数百万行代码的代码库中工作,其中一些代码可以追溯到1980年代。它只是软件,因此只需编写一些单元测试即可,因此您可以进行重构,使其变得更好。

这里的关键词只是-它是一个四个字母的单词,不属于任何程序员的词汇表,更不用说在遗留系统上工作的人了。

您认为编写单元测试和测试一小时的开发工作需要花费多长时间?为了讨论起见,让我们再说一个小时。

该百万线,拥有20年历史的旧系统投入了多少时间?假设,有20位开发人员使用了20年时间乘以2000小时/年(他们非常努力)。现在,让我们选择一个数字-您拥有新的计算机和新的工具,并且比起最初写这篇$%^^的家伙要聪明得多-假设您值得其中10个人。你有40个人年,好吗...?

因此,您的问题的答案还有很多。例如,该例行程序有1000行(我有几行超过5000行),它过于复杂,而且是意大利面条。只需几天(再加上四个字母的单词)就可以将其重构为几百行例程和更多的二十行助手,对吗?错误。在这1000行中隐藏了100个错误修复程序,每个错误修复程序都是未记录的用户要求或不明显的情况。这是1000行,因为原始的100行例程无法完成工作。

您需要以“ 如果没有破裂,请不要修复 ” 的思维方式进行工作。当它损坏时,在修复它时需要非常小心-随着它变得更好,不要意外更改其他内容。请注意,“中断”可能包含无法维护但可以正常运行的代码,这取决于系统及其用途。问“如果我搞砸了,使情况变得更糟,会发生什么”,因为有一天,你将不得不告诉老板的老板为什么选择这么做。

这些系统总是可以做得更好。您将有预算可用于工作,时间轴等。如果您不这样做,那就去做一个。当金钱/时间用完时,不要再做得更好了。添加功能,给自己一点时间使其变得更好。修复错误-再次花费一些额外的时间并使它变得更好。永远不要交付比开始时更糟糕的东西。


2
感谢您的提示!这些是您的还是书中的?
Armand

3
可能两者兼而有之-在完成这项工作几年后,我读了这本书,可能应该读得不错。像任何一本好书一样,它会使您挑战当前正在做的事情,加强您所做的大部分工作,但是并没有针对您所遇到的特定问题的所有答案。
mattnz

7
“这是1000行,因为原始的100行例程无法完成工作。” 因此,实际情况很少如此。通常是1,000行,这仅仅是因为原始开发人员卷起了袖子开始编码,然后才花了一点时间进行规划或设计。
史蒂芬·图瑟

3
不。我是说,在大多数情况下(我个人遇到过),有1000条行例程明确表明人们在考虑如何编写适当的抽象之前就开始编写代码。千行例程实际上从定义上讲太复杂了–您是在说一千行例程具有数百个隐藏的,未注释的错误修复程序,这是负责任的开发人员的标志?
史蒂芬·图瑟

16
如果您相信此站点上的每条帖子,那么每个人都必须处理1000行意大利面条代码,但没人写过。根据我的经验,开发人员的特征是1000(和10000)行例程,他们会竭尽所能地交付付薪水的老板对他们的要求。我觉得这很侮辱和自大,以至于许多开发人员在不了解情况的情况下随意在旁观地发表评论,而不必向社区公开自己的作品进行批评。
mattnz

19

这本书有两个要点。

  1. 旧版代码是没有测试范围的任何代码。
  2. 每当需要更改旧代码时,都应确保它具有覆盖范围。

正如其他响应者所指出的那样,试图抢先更新您现有的旧版代码是愚蠢的事。取而代之的是,每当您必须更改旧代码(用于新功能或错误修复)时,请花点时间删除其旧状态。


6
+1优点:“每当需要更改旧代码时,请花点时间删除其旧状态。”
约翰,

3
删除旧版身份,请投票:)
Rachel

7

简而言之,这就是事实—添加测试和重构。

但是本书为您提供了许多不同的技术来处理很难安全测试和重构的代码。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.