在项目管理团队中似乎有一种说法,指出“有效”意味着应该认为它已100%完成。大多数程序员都知道情况并非总是如此。如果我正在尝试其他方法来使某项功能正常工作,那并不一定意味着我找到了最好的解决方案,或者在与其他开发人员一起审阅后不需要进行任何重新设计。我经常会做一些事情,退后一步,然后问自己在满足业务规则后我能做些什么。这个“我可以做得更好”的时间是否应该真正放在时间轴内的某个地方?我认为最好的方法是,一定程度上,代码总是比发现时更好(这可能意味着启动后重构)。然而,
在项目管理团队中似乎有一种说法,指出“有效”意味着应该认为它已100%完成。大多数程序员都知道情况并非总是如此。如果我正在尝试其他方法来使某项功能正常工作,那并不一定意味着我找到了最好的解决方案,或者在与其他开发人员一起审阅后不需要进行任何重新设计。我经常会做一些事情,退后一步,然后问自己在满足业务规则后我能做些什么。这个“我可以做得更好”的时间是否应该真正放在时间轴内的某个地方?我认为最好的方法是,一定程度上,代码总是比发现时更好(这可能意味着启动后重构)。然而,
Answers:
在瀑布和敏捷中,有一个总体原则可以控制重构和优化的需求:YAGNI(您将不需要它)。第二个原则是第一个原则的推论:“过早的优化是万恶之源”,这与通用谚语“卓越的敌人就是完美”的编码等效。
让我们接受原理并应用它们。您需要构建一个ETL算法,该算法采用特定类型的文件,提取其信息,然后将该信息放入数据库中。您本周的目标(就我们的目的而言,无论您是在敏捷商店还是SDLC商店中都无关紧要)就是要做到这一点。
您是一个聪明的家伙,并且一览无余。您知道这不是项目需要ETL的唯一文件类型。因此,您考虑实现此ETL算法,使其也可用于另一种类型的文件,该文件只有很小的差异。这样做会违反YAGNI。您的工作不是为其他文件开发算法。它将在一周结束前为一个文件开发算法。为了达到该目标并通过验收测试,您需要开发该算法并使它正确运行。您“不需要”其他代码以使其与其他文件一起使用。您可能会认为这将节省您现在整合它的时间,您也许是对的,但您也可能犯错了。其他文件的算法可能需要在无法使用代码的系统区域中使用,或者新文件的要求可能与您所不知道的方式有所不同(在敏捷中,要求可能还不存在)。同时,您浪费了时间,不必要地增加了算法的复杂性。
现在,是下周,作为对您在第一种算法上的出色工作的杰出贡献,我们被赋予了为两种新文件类型创建算法的任务。现在,您确实需要其他代码才能使算法处理更多文件。您可以使用模板方法模式扩展现有算法,该模板方法模式将使用具有特定于文件的单个步骤的基本模式,或者您可以简单地从现有算法中派生出一个通用接口,在该接口之后开发两个新接口,并将其插入一个可以选择使用哪种算法的对象。
在开发过程中,您知道您有一个要求,即系统每秒必须处理10KB的原始数据。您进行了负载测试,发现您的初始草稿算法处理速度为8KB / s。好吧,这不会通过AAT。您看一下,发现算法中存在一些O(我的上帝)复杂性循环结构;您可以简化它并获得12KB / s。您认为“非常好”,但是“如果我的代码循环太差了,还能省什么呢?”。嗡嗡声您刚刚违反了“过早优化”规则。您的代码有效,并通过了所有要求。您“完成”了,直到需求更新为需要15KB / s的时间为止。如果发生这种情况,那么您将代码重新备份并寻找可改进的地方。
无论是在敏捷开发中还是在传统的SDLC中,在开发过程中都遵循以下简单过程:“在第一遍,使其正常工作。在第二遍,使其美观。在第三遍,将其设为SOLID。” 这就是说,当您第一次创建一行代码时,请确保该代码正确无误地完成其工作,但不要对代码中的设计规则过于关注,因为您现在所知道的就是永远不会再碰到这个区域。下次访问该行代码时,您只是证明自己错了;它不再是系统的一次性组件。为了可读性,代码的简洁性和/或DRY原理而对其进行重构(您可能已经复制粘贴了一些代码以执行五次;将其重构为循环和/或方法调用)。第三次您在该行代码中或周围工作时,
如果它可以正常工作,并且已经过测试,那么为什么要修复它?
这可能与您作为工程师/程序员的个人气质背道而驰,但是如果它有效,那么您有什么业务价值可以继续完善呢?随着时间的推移,它会更容易维护吗?如果是这样,那么在敏捷方法下工作,您应该能够在待办事项列表中创建新项目以细化和重构现有代码,并且这些项目将与待办事项列表中的其他项目优先。这是敏捷过程价值的一部分:团队共同决定最重要的事情以及下一步要做的事情。
我们的团队还跟踪我们称为“技术债务”的信息,因此,如果您可以进行某些工作,但知道可以做得更好,则将其记录为技术债务。我们使用scrum,有时您会尽早完成sprint中的所有工作(如果您与估算值相当接近,您应该大约提前一半的时间来完成),但没有足够的时间来投入全新的工作用户故事,因此我们会花费额外的时间来减少技术债务。它没有像积压的用户故事那样被正式跟踪,只要有时间我们就可以进行大量工作。
当您将任务称为“完成”时,这或多或少是对您的判断。如果您对代码所在的状态不满意,请不要将任务标记为完成。
在对重构感到满意之前,请勿将代码标记为100%完成。您只需要不断评估重构代码的成本/收益,因为如果您学习足够,您将总能找到使代码更好的方法。
我使用TDD的红色绿色重构方法。因此,我的重构已内置到我的开发中。对于大型重构(如更改基础模型或类似的东西),我会让管理层投入,首先花费时间。
如果我正在尝试其他方法来使某项功能正常工作,那并不一定意味着我找到了最佳解决方案,
...在这种情况下,您还没有100%完成...
或在与其他开发人员进行审核后不需要进行任何重新工作。
如果代码审查和后续的返工是开发生命周期的一部分,则直到所有这些都完成后,该功能才能再次使用。
我经常会做一些事情,退后一步,然后问自己在满足业务规则后我能做些什么。这个“我可以做得更好”的时间是否应该真正放在时间轴内的某个地方?
这取决于。如果这意味着重构,那么它应该是原始开发任务的一部分。如果这意味着要尝试一种可能更好的算法,那可能是一项单独的任务。
我认为最好的方法是,一定程度上,代码总是比发现时更好(这可能意味着启动后重构)。但是,项目团队通常对这种方法感到非常不舒服,因为如果再次可行,并且已经过测试,那么为什么要修复呢?
简而言之,因为代码可以在许多层次上被破坏。
它现在可以工作是一回事。从长远来看,它是否干净,可扩展和可维护是完全不同的事情。
有关更多详细答案,请参见此线程。
据我所见和已读,这是一个未解决的问题。因此,回避回答如“ YAGNI”和第一次就做正确的回答。事实是,敏捷中没有重构的地方-但我认为应该有重构的地方。
到目前为止,最好的答案是技术债务。不幸的是,这在许多企业中都是软件的悲惨现实,无论是采用敏捷方法还是非敏捷方法,都急于将其发布出去,这在所有企业中都是普遍的,但是在敏捷方法下,快速而又肮脏的解决方案被合理化为良好的东西:“满足最低业务要求”和“ YAGNI”(关于保持代码干净)。
如果每个人都进行了TDD,那将是非常棒的,如果所有开发人员都按照一个答案的建议进行第二次或第三次重构,那将是非常好的。但这在现实世界中不会发生。技能水平各异的开发人员几乎总是在寻求快速解决方案时走捷径。结果,代码变成了无法维护的代码,这使新开发人员花了几天时间才能解密,这会损害生产力并延迟期限。“不可维护”是指复制和粘贴解决方案,5000行类等。所有这些代码以及这些修复程序都是企业的核心!-我会说,在这些添加解决方案的情况下,没有YAGNI这样的东西!您将需要干净的代码-总是。如果代码不干净,您肯定会不需要它-看到自我实现的预言了吗?开发人员会竭尽全力根本不使用该代码,因为看起来太痛苦了。恶性循环一直持续下去,直到整个泥泞之球不得不被扔掉并改写。
所以我说-尽管代码重构不是一个适当的,独特的,值得拥有的故事型敏捷概念-但我们应该花些时间进行重构。现在,一些商店要求团队将其冲刺的20%用于技术债务。希望敏捷的拥护者能够改变他们对YAGNI的看法,并为重构提供一个单独的时间分配活动。如果他们已经知道并且我还没有听说过,请指出所描述的地方,因为我非常想知道。
O(my God)-complexity
令我发笑!