敏捷和瀑布式流程的时间表中,代码重构和优化应该放在哪里?


10

在项目管理团队中似乎有一种说法,指出“有效”意味着应该认为它已100%完成。大多数程序员都知道情况并非总是如此。如果我正在尝试其他方法来使某项功能正常工作,那并不一定意味着我找到了最好的解决方案,或者在与其他开发人员一起审阅后不需要进行任何重新设计。我经常会做一些事情,退后一步,然后问自己在满足业务规则后我能做些什么。这个“我可以做得更好”的时间是否应该真正放在时间轴内的某个地方?我认为最好的方法是,一定程度上,代码总是比发现时更好(这可能意味着启动后重构)。然而,

Answers:


13

在瀑布和敏捷中,有一个总体原则可以控制重构和优化的需求:YAGNI(您将不需要它)。第二个原则是第一个原则的推论:“过早的优化是万恶之源”,这与通用谚语“卓越的敌人就是完美”的编码等效。

让我们接受原理并应用它们。您需要构建一个ETL算法,该算法采用特定类型的文件,提取其信息,然后将该信息放入数据库中。您本周的目标(就我们的目的而言,无论您是在敏捷商店还是SDLC商店中都无关紧要)就是要做到这一点。

您是一个聪明的家伙,并且一览无余。您知道这不是项目需要ETL的唯一文件类型。因此,您考虑实现此ETL算法,使其也可用于另一种类型的文件,该文件只有很小的差异。这样做会违反YAGNI。您的工作不是为其他文件开发算法。它将在一周结束前为一个文件开发算法。为了达到该目标并通过验收测试,您需要开发该算法并使它正确运行。您“不需要”其他代码以使其与其他文件一起使用。您可能会认为这将节省您现在整合它的时间,您也许是对的,但您也可能犯错了。其他文件的算法可能需要在无法使用代码的系统区域中使用,或者新文件的要求可能与您所不知道的方式有所不同(在敏捷中,要求可能还不存在)。同时,您浪费了时间,不必要地增加了算法的复杂性。

现在,是下周,作为对您在第一种算法上的出色工作的杰出贡献,我们被赋予了为两种新文件类型创建算法的任务。现在,您确实需要其他代码才能使算法处理更多文件。您可以使用模板方法模式扩展现有算法,该模板方法模式将使用具有特定于文件的单个步骤的基本模式,或者您可以简单地从现有算法中派生出一个通用接口,在该接口之后开发两个新接口,并将其插入一个可以选择使用哪种算法的对象。

在开发过程中,您知道您有一个要求,即系统每秒必须处理10KB的原始数据。您进行了负载测试,发现您的初始草稿算法处理速度为8KB / s。好吧,这不会通过AAT。您看一下,发现算法中存在一些O(我的上帝)复杂性循环结构;您可以简化它并获得12KB / s。您认为“非常好”,但是“如果我的代码循环太差了,还能省什么呢?”。嗡嗡声您刚刚违反了“过早优化”规则。您的代码有效,并通过了所有要求。您“完成”了,直到需求更新为需要15KB / s的时间为止。如果发生这种情况,那么您将代码重新备份并寻找可改进的地方。

无论是在敏捷开发中还是在传统的SDLC中,在开发过程中都遵循以下简单过程:“在第一遍,使其正常工作。在第二遍,使其美观。在第三遍,将其设为SOLID。” 这就是说,当您第一次创建一行代码时,请确保该代码正确无误地完成其工作,但不要对代码中的设计规则过于关注,因为您现在所知道的就是永远不会再碰到这个区域。下次访问该行代码时,您只是证明自己错了;它不再是系统的一次性组件。为了可读性,代码的简洁性和/或DRY原理而对其进行重构(您可能已经复制粘贴了一些代码以执行五次;将其重构为循环和/或方法调用)。第三次您在该行代码中或周围工作时,


3
+1 O(my God)-complexity令我发笑!
Joel C

+1,让它首先工作。太多的人试图编写模式并过早地进行优化。
贾斯汀·

我发现这是作为程序员要克服的最困难的问题之一。工程师天生渴望进行实验,开发和完善,但是最终,您却获得了高薪。如果您花费太多时间和/或金钱而由于超支而被取消,那么完美的产品有什么好处?
ToddR

我喜欢实用的方法,但是“在第二遍,让它变得漂亮”时我有一个问题:如果第二遍是一年后,而您还不能确定变量和方法名是有意义的,并且幻数被符号常量替换了您可能难以理解代码。该如何处理?一个月或一年后,在“使其工作”之后1小时内“使它变得漂亮”要便宜得多。我同意,如果首先没有做过“使它漂亮”,那么在下一次代码更改时“使它漂亮”是有用的。
k3b

在敏捷/ TDD中,根据我的经验,第二遍通常会在第一遍之后不久发生。在瀑布式的SLDC中,您是正确的。该函数往往只编写一次,然后坐在那里,直到通过该方法接触到下一轮需求为止。因此,一些好的编码实践需要在第一时间发生,例如自记录代码,这样一年后回来时,您就可以记住该代码的功能以及以这种方式编写代码的原因。
KeithS

10

如果它可以正常工作,并且已经过测试,那么为什么要修复它?

这可能与您作为工程师/程序员的个人气质背道而驰,但是如果它有效,那么您有什么业务价值可以继续完善呢?随着时间的推移,它会更容易维护吗?如果是这样,那么在敏捷方法下工作,您应该能够在待办事项列表中创建新项目以细化和重构现有代码,并且这些项目将与待办事项列表中的其他项目优先。这是敏捷过程价值的一部分:团队共同决定最重要的事情以及下一步要做的事情。

我们的团队还跟踪我们称为“技术债务”的信息,因此,如果您可以进行某些工作,但知道可以做得更好,则将其记录为技术债务。我们使用scrum,有时您会尽早完成sprint中的所有工作(如果您与估算值相当接近,您应该大约提前一半的时间来完成),但没有足够的时间来投入全新的工作用户故事,因此我们会花费额外的时间来减少技术债务。它没有像积压的用户故事那样被正式跟踪,只要有时间我们就可以进行大量工作。

当您将任务称为“完成”时,这或多或少是对您的判断。如果您对代码所在的状态不满意,请不要将任务标记为完成。


2
我已经成为“技术债务”概念的拥护者,在此背景下提出了+1。
Patrick Hughes

完全忘记了“技术债务”的想法;好词。但是,我被告知要避免使用任何符合“技术债务”条件的东西,这意味着需要大量的开发人员周期才能进行重构。“轻巧地做”仍然意味着“正确地做”,只是不要在可能是一次性的代码上使用“象牙塔”。
KeithS

5

这个“我可以做得更好”的时间是否应该真正放在时间轴内的某个地方?

是。

在您开始编码下一个版本之前。

不要基于“直觉”进行重构。

根据下一个Sprint的实际故事进行重构。


2

在对重构感到满意之前,请勿将代码标记为100%完成。您只需要不断评估重构代码的成本/收益,因为如果您学习足够,您将总能找到使代码更好的方法。

我使用TDD的红色绿色重构方法。因此,我的重构已内置到我的开发中。对于大型重构(如更改基础模型或类似的东西),我会让管理层投入,首先花费时间。


1
直到代码所驻留的所有产品都失效后,代码才能“ 100%完成”。就像您在一个人的心脏停止永久跳动之前,作为一个人还没有“完整”。您将始终吸收新的信息,并被要求去做以前从未做过的特定事情,或者以一种更高效或更便宜的新方式来做同样的事情。同样,您的代码库将始终需要工作-新功能和旧修复-直到没有人使用该软件为止。
KeithS

2

“发布后重构”在回归测试和质量检查时间中具有您所忽略的隐性成本,另外它还带来了不处理报告的错误以及新的/请求的功能和更改的机会成本。坦斯塔夫

如果值得做的话,值得通过常规流程而不是特殊例外的方式确定任务的优先级。毕竟,您是团队的一部分,致力于共同的目标并随意扩展计划以适应固定的工作代码也会对其产生影响。

因此,一个真实的答案是:如果您知道要重构,那么可以将该时间安排为任务的一部分。如果您要进行Scrum /敏捷操作,请在时间框内执行清理任务。如果您是瀑布/螺旋形,则将重构作为过程的一部分,以进行代码审查并接受模块。


0

如果我正在尝试其他方法来使某项功能正常工作,那并不一定意味着我找到了最佳解决方案,

...在这种情况下,您还没有100%完成...

或在与其他开发人员进行审核后不需要进行任何重新工作。

如果代码审查和后续的返工是开发生命周期的一部分,则直到所有这些都完成后,该功能才能再次使用。

我经常会做一些事情,退后一步,然后问自己在满足业务规则后我能做些什么。这个“我可以做得更好”的时间是否应该真正放在时间轴内的某个地方?

这取决于。如果这意味着重构,那么它应该是原始开发任务的一部分。如果这意味着要尝试一种可能更好的算法,那可能是一项单独的任务。

我认为最好的方法是,一定程度上,代码总是比发现时更好(这可能意味着启动后重构)。但是,项目团队通常对这种方法感到非常不舒服,因为如果再次可行,并且已经过测试,那么为什么要修复呢?

简而言之,因为代码可以在许多层次上被破坏。

它现在可以工作是一回事。从长远来看,它是否干净,可扩展和可维护是完全不同的事情。

有关更多详细答案,请参见此线程


0

据我所见和已读,这是一个未解决的问题。因此,回避回答如“ YAGNI”和第一次就做正确的回答。事实是,敏捷中没有重构的地方-但我认为应该有重构的地方。

到目前为止,最好的答案是技术债务。不幸的是,这在许多企业中都是软件的悲惨现实,无论是采用敏捷方法还是非敏捷方法,都急于将其发布出去,这在所有企业中都是普遍的,但是在敏捷方法下,快速而又肮脏的解决方案被合理化为良好的东西:“满足最低业务要求”和“ YAGNI”(关于保持代码干净)。

如果每个人都进行了TDD,那将是非常棒的,如果所有开发人员都按照一个答案的建议进行第二次或第三次重构,那将是非常好的。但这在现实世界中不会发生。技能水平各异的开发人员几乎总是在寻求快速解决方案时走捷径。结果,代码变成了无法维护的代码,这使新开发人员花了几天时间才能解密,这会损害生产力并延迟期限。“不可维护”是指复制和粘贴解决方案,5000行类等。所有这些代码以及这些修复程序都是企业的核心!-我会说,在这些添加解决方案的情况下,没有YAGNI这样的东西!您将需要干净的代码-总是。如果代码不干净,您肯定会不需要它-看到自我实现的预言了吗?开发人员会竭尽全力根本不使用该代码,因为看起来太痛苦了。恶性循环一直持续下去,直到整个泥泞之球不得不被扔掉并改写。

所以我说-尽管代码重构不是一个适当的,独特的,值得拥有的故事型敏捷概念-但我们应该花些时间进行重构。现在,一些商店要求团队将其冲刺的20%用于技术债务。希望敏捷的拥护者能够改变他们对YAGNI的看法,并为重构提供一个单独的时间分配活动。如果他们已经知道并且我还没有听说过,请指出所描述的地方,因为我非常想知道。


“事实是敏捷中没有重构的地方” -我认为这不是一个真实的陈述。在敏捷中,只要有业务案例,就可以进行任何形式的开发,包括重构。如果没有商业案例,为什么要这么做呢?
Bryan Oakley

我想您有一点要简单点。从理论上讲,即使开发人员不产生任何功能上的变化,也可以制造出用于修复伪劣代码的业务案例,但这不会激怒敏捷精神-使用业务作为代理来证明工作合理性。然后我会说,重构活动超出了敏捷的范围-一种CYA活动(如果您愿意的话)-修复了无法维护的代码,因此它不会花费长期的业务费用,并且责怪开发人员。称其为“重构冲刺”之类的东西,但是必须有一个正式的场所。
blindcodifier9734 '04
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.