我们有责任改进旧代码吗?


64

我正在查看我编写的一些旧代码。它可以工作,但不是很好的代码。我现在比那时知道的更多,所以我可以改善它。这不是当前的项目,而是当前的,有效的生产代码。我们是否有责任退一步来改进我们过去编写的代码,还是正确的态度“如果没有破裂,就不要修复”?几年前,我公司赞助了一次代码审查课程,其中一项主要收获是,有时它已经足够了。继续。

因此,在某个时候您应该只称其足够好并继续前进,还是应该在认为可能更好的情况下尝试推动项目以改进旧代码?


您是在自己的时间里还是在公司的一角钱上这样做?
JBRWilkinson '02

42
在大多数地方,您的首要责任是为公司增值。如果您做的任何事情都没有直接增加利润,那么其他任何事情都是白费力气的。就像镀金一样,旧的经过测试的工作代码就是经过测试的工作代码,可以对其进行改进,使其变得更好,现在,它变成了未经测试的新代码因此变成了无法工作的代码,这并没有增加底线的价值。

7
问你的老板,他要你做什么。您很可能会被告知不要理会它。另外,以我的经验,代码更改仅应作为实际交付的一部分进行。随着时间的变化,随机更改引入错误的可能性太大,由于您没有立即想到的更改,因此修复时间太长。

1
在文档中添加一些有关可能改进的评论,然后就此保留?
James P.

2
编写单元测试或回归测试。不要更改代码,但是可以让某人稍后出现并自信地进行所需的更改,尽管他们并不熟悉代码。
James Youngman

Answers:


66

除非您要对此“旧代码”进行更改以修复错误或添加功能,否则我不会为了这个目的而进行改进。如果您确实想最终对其进行改进,请在开始重构之前,确保已使用适当的单元测试来测试代码。

您可以使用“旧代码”来学习更好的做法。如果您这样做,那是一种兼职学习的经验,您不应该期望该代码取代客户/客户当前发布或部署的代码。


4
我在想的是实用的程序员带来的“软件腐烂”和破窗理论以及软件熵的影响。pragprog.com/the-pragmatic-programmer/extracts/software-entropy
JMQ

5
除非您通过重构已经生效并投入生产的代码来为公司增值,否则很难为上级提供必要的时间来消除“软件腐烂”。仅当您将积极使用此代码时,才这样做,否则除了获得重构经验外,没有太多好处。
伯纳德

11
@jmquigley,只有在更改了源代码的情况下软件才会腐烂,并且只有在看到破损的窗口后才会起作用。只要不需要环境,旧的代码库就可以以相同的方式工作。
彼得Török

2
在“改善”错误的过程中,尽量不要将错误引入工作程序中;-)
robrambusch 2012年

4
我认为代码“烂”是一个不幸的隐喻。代码不会腐烂,如果您什么都不做,它根本不会改变。如果有的话,代码工作会变硬-在工作时会引入熵,并且可以通过花费大量精力进行重构来消除此熵(类似于重铸/伪造)
jk。

32

重构最需要修改的代码区域。由于您经常访问这些区域,因此重构将提高您对代码的理解,以及当您再次访问它们时的可读性,而重构代码毫无意义,没人会再看一遍。

此外,如果仅在需要修改代码区域时才对其进行重构,则在重构导致回归的情况下,它为您提供了有效的借口。当然,尝试用单元测试来覆盖重构,但这并不总是可能的,尤其是对于遗留代码,您应该期望大型重构会偶尔创建回归。

如果您需要添加功能并且您的设计使您的速度变慢或导致重复,请进行重构。当我设计代码时,我几乎永远无法准确预测将来将需要进行哪些更改。但是,当我添加新功能时,通常最终会重构共享代码。到那时,我已经添加了第三个功能/重构周期,我的重构已经付钱了,共享代码也相当稳定。

TLDR:根据需要进行重构,没有义务。


您能否更具体地说明“重构导致回归”的含义?重构的目的是在不更改软件行为的情况下改善其设计吗?能给我举个例子吗?
Manfred 2012年

3
@John:是的,这就是重构的目的:改进代码,但保持行为。
伯纳德'02

@John任何非平凡的重构都可能会无意间改变行为,尤其是在没有回归测试的情况下。
加勒特音乐厅

14

您所做的一切都是有代价的。您的编程时间有限。您在编程中所做的每一件事都应该被反对,“这样做有什么好处?” 和“做其他事情有什么好处?”

如果您不考虑机会成本(做其他事情的成本是多少?),那么质量是免费的。最好改进您的代码。您会学到一些东西。它将运行得更好。它会卖更多。

真正的问题是,随着时间的流逝,下一件最好的事情是什么?然后,您需要进行权衡。

它会出售更多软件吗?

它会减轻头痛吗?

你会学什么?

它会变得更加美观吗?

会提高您的声誉吗?

向队列中的此活动和其他活动询问这些问题(以及与您相关的其他任何问题),这将有助于回答是否值得解决。这些折衷就是为什么经济学对程序员很重要的原因。 乔尔在我之前就说过,一位老导师甚至在乔尔之前就对我说过。

或者,如果您想要一个更简单的答案,只需停止看电视,直到您修复了密码。:-)


4
要从不使用软件的真实示例中借用,一些运输公司会出于各种原因而向员工支付清洁和打磨钻机的费用,通常是因为这有助于驾驶员/操作员为“他们的”设备感到自豪,因此他们会更好地保重对此,并予以密切关注;快速方便地避免问题。同样,如果要行驶几英里,则上卡车并驾驶它,并担心在行驶几千英里后会清洗(沿海岸行驶)。
JustinC'2

@justinC-完全是!您的示例同时捕获了另一个原因和机会成本。
MathAttack

成本(或价值等)确实是正确答案的关键词。它应该在整体上增加价值,同时考虑到触摸旧代码可能会破坏东西(删除价值),无论看起来如何优化。
cregox

6

我认为您应该首先问自己一个似乎遗漏的问题。代码以哪种方式不好?因此,您实际上是在问自己以下问题:

  • 代码是否不执行应做的工作?
  • 维护软件时,代码是否会引起您的问题?
  • 代码是否完全独立?
  • 您是否计划在可预见的将来随时更新或替换代码?
  • 您是否可以提出合理的业务案例来更新您所关注的代码?

如果我多年来学到的一件事,那就是您不能在事实之后再进行一次猜测。每次您解决代码中的问题时,您都会学到一些东西,并且可能会看到您的解决方案(或类似的解决方案)如何可能是更好地解决几年前不同解决的问题的方法。这是一件好事,因为它向您表明您已经从经验中学到了。但是,真正的问题是,您之前编写的代码是否有可能成为遗留问题,随着时间的推移将变得越来越难处理。

我们在这里真正谈论的是困扰您的代码是否容易维护,以及随着时间的流逝维护的成本可能会很高。这本质上是关于技术债务的问题,现在是否值得通过少量的外科手术维护来偿还债务,或者债务是否足够小以至于您可以让它滑动一段时间。

这些是您确实需要权衡当前和未来工作量的问题,应该与您的管理层和团队进行详细讨论,以便更好地了解将资源投资于何处以及旧代码是否值得您可能需要花费的时间-如果有的话。如果您可以为引入变更提供良好的业务案例,则一定要这样做,但是如果您因为对编写方式的尴尬而面临着修改代码的冲动,那么我建议您不要在维护旧代码方面有个人自豪感的余地。它要么起作用,要么不起作用,它要么易于维护,要么维护成本高昂,它永远不会好坏,仅因为昨天没有您今天的经验。


5

绝对不要仅仅为了改进而改进它。正如其他人所说的(并且是常识),随着时间的流逝,我们所有人都会变得更好(“更好”的某些价值)。话虽如此,对代码(正式或非正式地)进行审查通常可以阐明这些点点滴滴,而我们可能希望这些点点滴滴不再成为现实。

尽管我不认为我们有责任回过头来改进从根本上不被破坏,不安全或不依赖于已弃用/ EOL列表中功能的代码,但在这种情况下,我过去曾做过一些事情:

  • 确定团队中真正挖掘和改进代码的人员,将其作为一种大脑清洁或一口小巧的任务来给人以成就感,并在计划中找到时间让他们定期进行。我一直在团队中至少有这样一种人,而且如果我们处在低潮或萧条的时期,这种方法还可以提高士气(或至少是心情)。

  • 使用它作为学习练习的基础。对于实习生,学生或团队的新成员或初级成员,在团队高级成员的指导下重构旧代码将使他们有机会与新团队成员进行交流,了解更多有关系统的知识,并养成编写/更新单元测试并进行持续集成。重要的是要注意,此练习是在指导下完成的,并且明确地设计为使代码更好的练习因为它不符合当前的标准/规范。

因此,没有责任对其进行修复,但是旧内容可能确实有用。单元测试和CI是您的朋友!


4
向新手提供错误的代码是项目管理中最糟糕的反模式,他们看到它并认为它是正确的并且只是复制它,由于这样的错误建议,错误的代码像癌症一样传播。

1
@JarrodRoberson感谢您指出我应该变得更加明显的内容;我已对答案进行了编辑,以注意,作为学习经历的一部分,我非常专门地执行此操作,并且他们正在与导师一起工作。这不是将它们扔到最深处的情况。
jcmeloni 2012年

我仍然认为它的用语是人们会读到“把它交给新手,尤其是实习生和学生”。并在那里停止阅读理解。如果说它是从编程XP风格的高级会员和初级会员对开始的,那么可能还不错。我在镀金方面存在问题,并且为了更改第一个项目要点而增加了更改内容的风险。

1
代码审查用于防止不良代码进入版本控制,而不是在事后识别不良代码,这很晚了。

@JarrodRoberson感谢您指出我的语言含糊不清,但很可能会引起误解;我进行了更多编辑,请耐心等待当前的状态。
jcmeloni 2012年

2

不必要。但是,如果您正在执行代码维护,并且偶然发现可能会更好的东西,则可以更改它,前提是您具有适当的单元测试以确保未创建回归。

如果不存在这样的测试,并且您不确定它的行为是否应该正确,则最好不要进行测试。


4
我要添加“并且,如果进行更改,不会为计划的时间表增加很多时间”
HLGEM 2012年

2

从工程师的角度来看,请确保我非常想处理旧代码,直到不能再对其进行改进了。但是是否有商业案例呢?归根结底,该代码有助于提高底线,即您的工作场所的盈利能力。如果不是,则将其保留。

有一个很大的警告,如果通过改进代码来避免发生错误,(考虑这里的大型Y2K问题。)我肯定会与更高层的人(也许是您的业务部门经理)联系,并讨论改进代码的后果。


2

对于我来说,这个问题可以改写和概括为:“如果现在那段具体的代码行之有效,为什么有人应该花更多的资源(时间,金钱,精神等)?这是否浪费资源? ?

每次找到旧版代码时,我都会考虑一些似乎很重要的事情。

  1. 我要做什么改变?
  2. 我需要支持此代码吗?它会在多久之前(不久/将来)发生?
  3. 此代码足够舒适使用吗?(马上)
  4. 我可以确定自己所做的所有更改都是安全的吗?通常,不同的测试可以帮助回答这个问题。
  5. 如果我在代码修改过程中犯错,会遇到什么后果?是否可以快速还原我的更改?会浪费时间吗?
  6. ...

实际上,您应该问自己很多问题。没有完整的最终清单。只有您和您的队友才能找到答案。

PS:我注意到我倾向于经常重写代码,而我的朋友和队友则倾向于保持不变。这是因为我们回答上述问题的方式有所不同。我不得不说,我们经常错误地回答他们……因为我们无法预测未来。


2

Microsoft是否需要更新Windows?所有* nix发行版都必须不断发展吗?还是一个更实际的例子,是否每个人都还在驾驶1970年代的汽车?


1

通常,您可以在第二轮更好地编写代码,您可以通过最初编写来了解有关该域的更多信息。

没有值得一提的简单答案。通常,除非a)对您来说是一个很好的学习专长,或者b)长期使用更好的代码可以节省时间,否则您不应该这样做。记住每一个变化都会带来错误。

附带说明一下,我会大力提倡单元测试。进行重新整理非常容易,特别是如果您没有通过自动休息清楚地标记当前行为。


1

我相信,我们有责任编写当今最好的代码。这意味着要利用过去学到的一切,并拒绝在设计中走捷径。如果进度压力导致某些问题被削减,我什至不认为我们的软件的质量应该被考虑,反而是整洁的动画小纸夹...

现在,如果您正在工作,并且发现您需要与之交互的代码没有达到您当前能够编写的级别,那么如果您能够以受控的有条理的方式进行操作,则可以对其进行修复。我个人对这种重构的经验非常有限,就像每个人(几乎每个人?)一样,我尝试了整个“让一切都改变并祈祷它能起作用”的尝试,并对此感到非常痛苦。我建议研究一下马丁·福勒(Martin Fowler )关于此事的讨论(他的书许多文章之一)。他似乎启发了当前有关该过程的大多数想法。

当然,有时您可能无法根据需要清除代码。Joel Spolsky写了一篇文章,介绍为什么您可能要花几个星期来简单地重构代码。在这里阅读它,是的,它有点旧,但是我认为信息仍然有用。

希望对您有所帮助


1

我觉得重构/改进旧代码定义了程序员自己。想要改善您一年前编写的代码只会显示您的进度,如果它使应用程序更好,并且您有能力,时间和批准来进行改进,则可以这样做。


1

更好/改进的是多轴比较。您是否认为您可以使其更快,更小,更节省资源,更易读,更有用的信息,更精确的结果,更灵活,更通用,能够在更多系统上运行,消除对单独产品的依赖?

您的公司为什么要付钱给您花时间重写此代码,而不是编写新代码或重写其他代码?

您应该在机会出现时进行改进,但是机会意味着您已经在编写代码,或者您已经确定进行更改的商业原因。

推动生产变更会带来不零的破损机会(单元测试和功能测试只会减少这种机会,而不会消除这种机会),只有在预期收益大于风险的情况下才应该进行。

还要考虑的另一点是-您打算将这种更改推向生产还是仅仅推向开发部门?两种情况的标准完全不同。如果它只是在开发部门中进行,并且可能永远不会投入生产,那么机会基本上意味着您出于某种原因正在查看代码,并且这样做并不费时。它可以如果推送应该不会发生如必需的,如果它被认为是在无端冷落进行审查时间。另一方面,如上所述,如果现在要投入生产,则需要考虑这种更改是否值得:就进行推送所花费的时间以及使用新代码的好处而言。


不想将生产代码更改推入生产环境?但是保留在开发部门吗?嗯。不要以为我会接受。它只会使以后的开发变得混乱和复杂,因为没人会确定是否应该再次更改它,或者不遵守打算用于生产的其他更改。
Marjan Venema

@MarjanVenema:开发停止时,所有分支都应该相同。如果您以后发现可以改进但没有改进的地方,请在开发分支中对其进行改进,然后将其保留在那里,等待开发恢复并进行新的推动。
jmoreno'2

啊,好的,我明白了。对我来说,这意味着它仍打算在不久后投入生产。除非您确保问题跟踪系统中存在伴随的问题,否则这是相当大的风险,这样测试人员/质量保证部门也可以对您的“改进”有所帮助。否则,随着其他变更的进行,他们将使其未经测试就进入生产。
Marjan Venema'2

@MarjanVenema:也许我应该说打算立即将其投入生产。如果您对更改永远不会被推到产品上感到肯定,请不要进行更改。如果是OTOH,您不确定,但是更改很容易完成,而您已经在那...进行更改。至于跟踪和测试,这将包含在“按需复查”中。
jmoreno

嗯,我想除非它与我的工作直接相关,否则我将选择不进行更改。而且,由于每个问题都有分支,所以我总是知道什么时候(哪个版本)投入生产。另外,我真的感到所做的任何更改都需要测试,而不是“按要求”进行审查。人们对构成风险的评估是不同的,并且第二双眼睛永远不会误入歧途。再说一次,我主要处理服务器端代码,其中的更改可能会巧妙地影响返回给客户端的结果。更改客户端代码的风险评估可能更为直接。
Marjan Venema'2

1

一条好的经验法则是,如果花了一些时间来了解代码的作用,并且如果可以通过一些精心选择的重构来减少这段时间,那么您将通过以下方式满足业务和团队的需求:采取这些步骤。

如果代码无法从您的分析中受益,如果字段名称没有表达代码意图,并且方法没有细分为可读的块,那么企业将失去价值:您的理解力。借助Visual Studio和ReSharper之类的工具,这些类型的重构是安全的,逻辑中立的,并且对于将来的开发人员生产力和信心具有潜在的巨大价值。

正如鲍勃·马丁叔叔说的那样:“永远离开营地,要比发现的要干净。”


1

这是一个要问贵公司管理层的问题。

您是否有时间和资源来回头修改旧代码?

您是否有时间和资源让QA团队测试您所做的更改,以确保它不被破坏?

在进入错误修复模块之前,我已经陷入了陷阱,然后看到我或其他人编写的代码效率低下或不雅致,对其进行更改,最终比我刚刚解决的问题多得多我受命修复的错误。


0

这取决于。

如果所讨论的代码确实被破坏,从而包含不可避免地会在某个时刻浮出水面的错误(例如,某些计数器在某个时候会溢出并导致令人讨厌的问题),那么解决这些问题可能值得付出努力-但是如果您这样做,首先要采取所有可能的保护措施,以避免引入新的错误:确保您拥有涵盖您所涉及的所有内容的有意义的单元测试,让所有有资格的人员审核所有更改,坚持进行彻底的测试,确保您可以恢复到原来的状态随时更改版本,在生产之前备份任何数据,先部署到验收环境并由实际用户进行测试,等等。您还需要获得批准才能继续进行:如果该错误确实是定时炸弹,而您的经理有些称职,您将能够说服他/她解决该问题(如果您未获得批准,则可能表明您错了)。

OTOH,如果您的抱怨仅仅是缺乏代码优雅性,那么您就不敢碰它。它已经在生产环境中提供了忠实的服务已有一段时间了,更改代码只会满足您的要求,而不会增加任何价值,并且像每次更改一样,存在破坏某些内容的风险。即使您没有这样做,您的时间也很宝贵(从字面上看:您的工作得到报酬,所以您的每一分钟都花钱),并且由于您没有增加任何实际价值,因此这样的更改将是公司和项目的净亏损。

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.