如何克制自己从压倒性的要求改写一切的冲动?

build立

你有没有经历过一段代码去做一个看起来很简单的改变,然后意识到你刚踏入一片值得认真关注的荒地? 这通常得到一个正式的FREAK OUT时刻,在那里重写所有在眼前的压倒性的感觉开始爬起来。

重要的是要注意,这个不好的代码不一定来自其他代码,因为它可能确实是我们过去编写或贡献的东西。

问题

很明显,有一些严重的代码腐烂,可怕的架构等需要处理。 与这个问题有关的真正问题是, 现在不是重写代码的正确时机 。 这可能有很多原因:

  • 目前处于发布周期的中间,因此任何更改都应该是最小的。
  • 凌晨2点,大脑开始closures。
  • 这可能会对计划造成看似不利的影响。
  • 兔子的洞可能比我们目前所能看到的要深得多。
  • 等等…

那么我们应该如何平衡不断改进代码的责任,同时又是一个负责任的开发者? 我们如何避免为破窗理论作出贡献,同时也意识到行为和潜在的鲁莽可能造成的?


更新

很好的答案! 大多数情况下,似乎有两个思想stream派:

  1. 不要拒绝这样的冲动,因为这是一件好事。
  2. 不要屈服于诱惑,因为它会把你烧毁在地上。

知道更多的人是否觉得有平衡是很有意思的。

我是制作名单的忠实粉丝!

一旦这个冲动让你重新写一些东西 – 花10分钟时间列出需要重写的东西。 遵循所有将您进一步引入需要注意的代码的列表,并列出这些代码。

希望在相对较短的时间内,您将拥有两件事情之一:

  • 一个很长的名单,完全放弃你想再次重写任何东西。
  • 一个名单实际上并不长,所以为什么不放纵自己,去重写?!

我发现,花两个月的时间修复由于我的“无害”重写而引起的错误,足以在没有明确的授权/项目计划的情况下治愈我这种冲动。

对于我来说这个最难忘的项目大概是在4年前,当我被叫到远程办公室来帮助一个项目,这个项目在一个星期后才会提交给客户,而且根本没有工作。 这个项目主要是向印度外交的,国际海事组织(IMO),一个项目pipe理的失败导致了大量的意大利面代码太碎片化,无法正常工作。

经过一整天的审查,我向pipe理层介绍了我的意见,即项目只需要大规模的重构和重组,否则就永远不能正常工作。 这次讨论的结果是6天20小时的工作/ 4小时的睡眠,其中2次我真的在公司大厅的沙发上睡觉,因为开车回酒店的时间浪费了。

代码的主要改进包括:

  • 应用命名标准
  • 移动到源代码pipe理
  • 开发一个构build过程
  • logging各个组件

原来的大部分代码都保留了下来,只是简单地移动和重组/重构,使其长期可持续。 这周是地狱吗? 当然。 它是否使项目更成功? 是的。

我不能忍受意大利面代码,我经常捐出我自己的时间来解决这个问题。

如何克制自己从压倒性的要求改写一切的冲动?

变老*

这一切都发生在我身上,我已经逐渐失去了重写一切的冲动。 为什么?

  • 一旦你做了几次,你会意识到你经常会比开始时更糟。
  • 即使你是上帝给程序员的礼物,而你的辉煌的重写也没有引入任何新的bug,你根本就没有注意到或者实现大约30%依赖的小型边缘特征/ bug。 这将花费你几个月的时间来修复
  • 没有什么能像时间一样消除不合理的繁荣。 通常这是一个可悲的损失,但在这种情况下,这是一个胜利。

*(如果你缺乏空闲时间,那么更多的经验也可能是一个合适的替代品)

重写的冲动是正确的,只要:

  • 你“冻结”现有的代码(带有标签)
  • 你在一个单独的分支开始重写尝试
  • 你准备第一个unit testing,以确定当前的行为,并确保您重现现有的function…

也就是说,你必须平衡重写过程和遗留代码的度量稳定性。
“如果没有损坏,请不要修理”;)

这不是一个答案,但阅读美丽的文章“小代码差异自恋”可能会有所帮助。

你完全正确的说,有一个正确的时间和错误的时间来重写(和不稳定)的代码。

让我想起了一位我认识的工程师,他有一种习惯于潜水的习惯,并且每当他觉得这样做的时候都会进行重大的改写。 这导致质量保证人员把他的产品放在了墙壁上 – 如果他报告一些关于一些微不足道的错误,这个错误就会被修复,但是工程师在修复这个错误时注意到的主要重写会引入另外50个新的错误那么质检工作人员需要追查。

所以要想改写自己的方法就是要让QA工程师的脚步行一英里,这个工程师必须对所有这些新的错误进行testing,诊断和报告。 也许甚至可以借助QA部门几个月的时间来获得他们所从事工作types的个人感受(如果您从未这样做的话)。

另一个build议是为自己写一个规则来描述任何变化。 当你检查代码更改到源代码控制时,也许发布这些笔记。 你可能会被动机,以这种方式尽可能less的变化。

只是不要 – 兔子洞总是太深了。 做出任何小小的局部变化,让这个地方变得比你发现的更干净,但是当你警觉并且有足够的时间燃烧时,会留下很大的重构。

在sourcemaking.com的小型阶段处理大型重构的一个不错的入门者 :

你必须像汉塞尔和格莱特尔一样,轻咬一下边缘,今天稍微多一点,明天再多一点

就个人而言,这是JIRA或Bugzilla等bug跟踪软件与我一起进入的地方。

当我看到他们的时候,我没有修好所有破窗户,但是如果情况很糟(时间允许),我会打开一张票,把它分配给我,或者分配给负责人,这样我不要切线。

– 我只做对他们需要做的事情,但是这个问题是有logging的,并且会及时修复。

– 这并不是说小破窗应该这样处理, 小问题应该永远是固定联系恕我直言。

  1. 重读“重构”。
  2. 拿一张纸,并列出“臭味”清单。
    (对于BadSmells()中的每种气味{
    打印smell.name;
    }
  3. 向代码添加评论,包括列表中的项目。
    while(odorPersists()){
  4. 通过清单,一次激光聚焦在一个气味。
    }

就我而言,如果你没有比重写代码更好的事情,那么你应该让其他人知道, 只是做 。 显然,如果需要几天的时间才能得到任何结果,而且这种变化意味着过度的停机时间,那么这不是一个好主意,但最终代码将成为一个问题。 让其他人意识到代码是可怕的,并试图获得某种运动来重写它。

上述陈述的问题在于,作为程序员/开发人员,您总是会有其他的事情来保持自己的忙碌。 只要把它放在待办事项的低优先级列表上,所以当你为某些工作而苦苦挣扎的时候,你可以随着重写来保持你的节奏。

我从来没有工作过任何特别敏捷,所以我做的是:

1)弄清楚是否有一个不涉及重写的合理解决方法。 如果不是的话,那么清除一些时间(也许通过向其他人解释修复有多困难)并进行重写。

2)有一个合理的解决scheme,没有重大的改写。 应用修复程序,运行testing,检查它,将错误标记为已修复。

3)现在,提出一个新的错误/问题(增强请求),概述提议的重写以及它如何改进代码(更简单?更易维护?减less耦合?影响性能或资源使用?)。 把它分配给我自己,CC任何有兴趣的代码。

4)给人一个评论的机会,然后在我现有的任务中优先考虑这个新的错误。 这通常意味着现在不这样做,因为大部分时间如果我有一个“适当的”错误来修复,那么我至less有两个。 一旦关键清单被清除,或下一次我需要做一些不枯燥的事情时,就去做。 或者也许在几天之后,似乎没有什么值得再做的事了,而且也不会完成,而且我已经节省了花在做这件事上的时间。

我认为,重要的是每当你做一个小小的修补程序时,避免刮胡子 。

这个权衡是,如果你想要重写的代码真的很糟糕,那么很容易将重写的优先级降到最低,而你最终花费了太多的时间来维护它,以至于你没有时间用一些将需要较less的维护。 这需要铭记在心。 但是无论重写应该是什么优先级,或者你的组织如何分配这些优先级,在相同的代码区域修复不好的devise与纠正导致最初进入的崩溃的逐个错误不是一回事处理。 这必须在步骤1中考虑:如果devise意味着潜在的代码中可能存在大量其他的逐个错误,那么修复这个错误可能是不合理的。 如果确实是一个错字,但是由于您打开了文件,您碰巧发现了一个重构机会,那么更正它并且不触及其他任何东西都是“合理的”。

很明显,你的店铺越灵活,你可以做的重构越有意义,如果它不是如此破坏性的/耗时的/政治的,就需要单独的任务。

乔尔有一篇关于这个的文章 :

有一个微妙的原因,程序员总是想扔掉代码并重新开始。 原因是他们认为旧代码是一团糟。 这里有一个有趣的观察: 他们可能是错的

如果它是你inheritance的代码,那就开始编写代码吧。 编写unit testing,然后重构。

不好的代码不是完全可以避免的,但可以通过适当的抽象来隔离。 如果确实是荒地,也就是说周围没有垃圾填埋场,重点devise过程比试图让人们编写完美的代码更有效。

不要以为你应该阻止自己。 大多数情况下,如果你觉得重写大部分是正确的。 我疯狂地不同意Joel Spolsky在这件事上

虽然这是我不同意他的几个地方之一…)

在足够好的时候停止重写。 为此,您不仅需要知道您的雇主有什么好的计划。 毕竟你做生活的编程不好的印象。 制定合理的标准,确实会告诉你,你是好的,结果是下降,是时候去下一个任务。 你应该喜欢你的程序,而不是那么你的老板喜欢他们。

编写更多的unit testing只是为了发现代码运行的很好。

如果你仍然有重写它的冲动,你会有一些testing来发现你的重写代码现在失败了;)

只有当你的老板/公司真正鼓励它的时候,才会重构,否则你将会频繁地花费额外的时间来提高代码的完美性……直到没有专注的人再次触摸它。

开始假设:你已经“提早做,经常做”。

那么开始重构从来就没有什么不好的时候,因为在任何时候都可以很容易地退出。 我发现,一开始总觉得这很容易,但是经过一些改变,看到效果之后,我开始意识到这将是一个多么大的工作。 现在是时候问是否真的有时间做出改变,或者直到下一次来到这个代码是否更好。

停止的意愿,扔掉一个半重构的分支,并在适当的地方做到这一点很快速,但是很关键。

这是为了重构,其中的变化是渐进的,运行(或近乎运行)的软件让你保持良好的接地。 重写是不同的,因为直到你找出需要的时间比你想象的要长得多。 我可能会从字面上理解这个问题,但几乎没有什么时候把它扔掉,重新开始。