你如何阻止永久持久的临时解决scheme?

说一个问题有两种可能的解决scheme:第一种是快速但是很冒险; 第二个是可取的,但需要更长的时间来执行。 你需要快速解决这个问题,所以你决定尽可能快地进行破解,计划在之后开始更好的解决scheme。 问题是,只要问题得到缓解,就会下降到待办事项列表中。 您仍然计划在某个时候提供更好的解决scheme,但是现在很难certificate它是正确的。 突然间,你发现你已经花了五年的时间使用不完美的解决scheme,诅咒它。

这听起来很熟悉吗? 我知道这是我工作的地方不止一次。 一位同事故意描绘了一个不好的graphics用户界面,以免长期意外采用。 你有更好的策略吗?

编写一个黑客失败的testing用例。

如果你不能写一个黑客失败的testing,那么黑客毕竟没什么问题,否则你的testing框架是不够的。 如果前者在你不必要的优化浪费你的生命之前快速跑掉。 如果后者,寻求另一种方法(无论是举报黑客,或testing…)

策略1(几乎从未select):不要执行kluge。 甚至不要让人们知道这是可能的。 只是第一次做正确的方法。 就像我说的,由于时间的限制,这个几乎从来没有被选中。

策略2(不诚实):谎言和欺骗。 告诉pipe理层,黑客中存在缺陷,以后可能会导致重大问题。 不幸的是,大多数时候,pipe理人员只是说,等到虫子成为问题,然后修复臭虫。

策略2a:与策略2相同,除了确实存在缺陷。 同样的问题,虽然。

策略3(和我个人最喜欢的):尽可能devise解决scheme,并做得足够好,实习生或代码猴可以做到这一点。 花费less量的代码 – 猴子钱比certificate你自己的工资要合理得多,所以它可能就完成了。

策略4:等待重写。 继续等待。 迟早(可能迟些),有人将不得不重写这个东西。 不妨做到这一点吧。

这是一篇关于技术债务的伟大的相关文章。

基本上,这是债务与您所做的所有技术决策的类比。 有很好的债务和坏账……而且你必须用最less的长期成本select要达到你想要的目标的债务。

最糟糕的债务是小小的积累快捷方式,类似于信用卡债务…每个人都没有伤害,但很快你是在穷人的房子。

在完成期限驱动的工作时,这是一个主要问题。 我发现添加非常详细的评论,为什么select这种方式,并提示如何编码的帮助。 通过这种方式,人们可以看到代码,并保持新鲜。

另一个可行的方法是在你的跟踪框架中添加一个bug.feature(你确实有一个吧?),详细说明返工。 这种方式是可见的,并可能在某个时候强制这个问题。

唯一一次你可以certificate修复这些东西(因为它们并不真正被破坏,只是丑陋的)是当你有另一个function或错误修复触及相同的代码段,你也可以重写它。

你必须根据开发人员的时间花费math。 如果软件需求得到满足,唯一错误的是代码在引擎盖下让人困窘,这并不值得修复。

整个公司可能会倒闭,因为过度热心的工程师每年都要在重新架构的时候坚持重新架构。

如果它没有bug并且符合要求,那就完成了。 装运它。 继续。

[编辑]

当然,我并不是主张一切都被黑了。 您必须在开发过程的正常过程中仔细devise和编写代码。 但是当你最终只需要快速完成黑客时,就必须对是否值得清理代码进行成本收益分析。 如果在应用程序的整个生命周期中,你会花费更多的时间来编写一个混乱的黑客,而不是修复它,然后修复它。 但是,如果不是这样,那么重新编写一个工作正常的,没有bug的应用程序太昂贵又冒险,因为只要查看源代码就可以让你生病。

你不要做临时解决scheme。

有时我觉得程序员只是需要被告知。

对此抱歉,但认真 – 一个hacky的解决scheme是毫无价值的,甚至在第一次迭代可能需要比正确的解决scheme的一部分更长的时间。

请停止留下我的垃圾代码来维护。 总是代码是正确的。 不pipe多长时间,谁喊你。

当你在早上交付的时候坐在那里,其他人正在debugging他们愚蠢的黑客,你会感谢我。

即使你不认为自己是一个优秀的程序员,也应该尽力做到最好,不要走捷径 – 不花时间去做正确的事情。 如果你不相信我,我可以certificate这个说法是正确的。

突然间,你发现你已经花了五年的时间使用不完美的解决scheme,诅咒它。

如果你诅咒它,为什么它在TODO列表的底部?

  • 如果它不影响你,你为什么诅咒它?
  • 如果它影响到你,那么这是一个需要立即解决的问题。
  • 我确信,在短期修复进入后,我特别关注长期修复的优先性。
  • 我详细说明了为什么这是一个黑客而不是一个好的长期解决scheme的原因,并使用这些方法让利益相关者(经理,客户等)了解为什么需要修复
  • 根据情况,我甚至可能会在这里注入一些最坏的情况。 “如果这个安全线路卡住,整座桥可能会崩溃!”
  • 我负责提出一个长期的解决scheme,并确保它得到部署

这是一个很难的电话。 我已经做了个人事业的黑客,有时你必须把这个产品从客户那里拿到手里。 不过,我照顾它的方式就是做。

告诉项目主pipe或你的老板,或客户:有些地方需要清理,编码更好。 我需要一个星期的时间来完成这个任务,而现在这样做的成本会更低,那么从现在起6个月,我们需要在子系统上实现一个扩展。

通常这样的问题是由于与pipe理层或客户沟通不畅造成的。 如果解决scheme适用于客户,那么他们没有理由要求更改。 所以他们需要被告知事先做出的权衡,这样他们可以在实施快速解决scheme之后计划额外的时间来解决问题。

如何解决它取决于为什么这是一个不好的解决scheme。 如果你的解决scheme不好,因为它很难改变或维护,那么第一次你需要维护和多一点时间,那么现在是升级到更好的解决scheme的正确时机。 在这种情况下,如果您告诉客户或您的老板,您首先使用了快捷方式,这会有所帮助。 这样他们就知道他们不可能期待下一次快速的解决scheme。 压缩用户界面可以是确保客户回来修复东西的好方法。

如果解决scheme不好,因为它有风险或不稳定,那么你确实需要和做这个计划的人谈谈,并且有一段时间来计划解决这个问题。

祝你好运。 根据我的经验,这几乎是不可能实现的。

一旦你因为受到压力而陷入黑客的泥沼,那么你也可能习惯于随时随地生活。 几乎没有足够的时间来重新工作,而不pipe内部实施得有多糟糕。 是什么让你觉得你会奇迹般地有更多的时间“在某个晚些时候”修复黑客?

我能想到的唯一例外就是如果黑客完全阻止你实现客户所需的另一项function。 那么你别无select,只能重做。

我尝试构build这个hacky解决scheme,以便尽可能无痛地迁移到长远的方式。 假设你有一个正在SQL Server中构build数据库的人,这是他最强大的DB,但是你的企业标准是Oracle。 使用尽可能less的不可转移的function(如位数据types)来构build数据库。 在这个例子中,避免位types并不难,但是它使得后面的过渡更容易。

教育谁来负责做出最后的决定,从长远来看,做事的做事方式是不好的。

  • 用可能涉及的方面描述问题。
  • 包括成本,生产力和收入曲线图。
  • 教他们关于技术债务 。
  • 定期重构,如果你推动。
  • 切勿在非技术人员面前称之为“重构”或“回头清理”。 相反,称之为“适应”系统来处理“新function”。

基本上,不了解软件的人不会得到重新审视已经工作的概念。 他们看待这个问题的方式,开发人员就像机械师一样,每当有人想要添加一个function时,他们都想继续拆卸和重新组装整个车辆,这听起来很疯狂。

这有助于比喻日常事物。 向他们解释,当你做出临时解决scheme时,你做出了适合快速build造的select,而不是稳定,可维护等。就像select用木头代替钢材一样build造,因为木头更容易切割,您可以更快地构build临时解决scheme。 但是,木材根本无法支撑20层build筑的基础。

我们使用Java和Hudson进行持续集成。 “临时解决scheme”必须评论:

// TODO: Better solution required. 

每次哈德森运行一个构build它提供了每个TODO项目的报告,以便我们有一个最新的,高度可见的logging任何需要改进的优秀项目。

伟大的问题。 这也困扰了我很多,大多数情况下,我是我自己的项目中唯一负责优先考虑问题的人(小企业)。

我发现需要解决的问题通常只是问题的一个子集。 IOW,需要紧急修复的客户并不需要解决所有的问题,只是其中的一部分 – 更小或更大。 有时,我可以创build一个解决scheme,而不是解决完整的问题,而只是针对客户的子集,这使我可以在问题跟踪器中留下更大的问题。

这当然可以不适用于你的工作环境:(

这让我想起了“CTool”的故事。 一开始CTool是由我们的一个开发人员提出来的,我会叫他Don,作为解决我们遇到的问题的一种可能的方法。 作为一个勤劳努力的工作types的唐,塞掉了,并交付了一个工作原型。 你知道我要去哪里。 一夜之间,CTool成为公司工作stream程的一部分,整个部门都依赖于它。 在第二天或第三天,痛苦的抱怨开始stream传出来,关于CTool的缺点。 用户质疑唐的能力,承诺和智商。 唐的抗议,这是从来没有被认为是一个生产应用程序听而不闻。 这持续了好几年 。 最后,在Don离开之后,有人开始重新编写应用程序。 这时候,对CTool这个名字附带了太多的厌恶,把它命名为CTool version 2是不可能的。 CTool甚至还有一个正式的葬礼,有点让人想起办公空间的复印机(或者是打印机)执行场景。

有些人可能会说,因为没有正确的修理CTool,所以唐应该是吊索和箭头。 我唯一的一点是,说你永远不应该破解一个解决scheme在现实世界中可能是不合理的。 但是,如果你是一个人,谨慎行事。

  • 把它写下来(一封电子邮件)。 所以当它成为一个问题后,pipe理层就不会“忘记”它应该是暂时的。

  • 使其对用户可见。 越是显而易见的是,当危机结束时,人们越不可能忘记回去做正确的事情。

  • 在临时解决scheme到位之前进行协商,以获得真正的解决scheme。实际解决scheme的工作可能应在临时解决scheme完成后立即开始。

你在自己的“修复”中提出了第二个非常具有描述性的错误,并在受影响的区域提出了一个“待办事项评论”:“这个领域需要很多工作,参见缺陷#555”(使用正确的课程数) 。 说“不投机”的人似乎不了解这个问题。 假设你有一个需要现在运行的系统,你的非黑客解决scheme是8天的工作,你的黑客是38分钟的工作,黑客是在那里买你的时间做的工作,而不是亏钱你正在做。

现在,您还必须让您的客户或pipe理层同意安排N * 100分钟的时间来完成真正的修复,除了现在需要的N分钟来修复它。 如果你必须拒绝实施黑客,直到你得到这样的协议,那么也许这就是你必须做的,但是我在这方面与一些理解的人一起工作。

引入快速修复的真正价格是当别人需要引入第二个快速修复时,他们会根据您自己的快速修复来引入它。 所以,快速修复的时间越长,它就会变得越坚固。 通常情况下,黑客只会比正确处理更长的时间,直到遇到第一个黑客攻击。

所以,显然这是(或似乎是)有时需要引入一个快速修复。

假设你的版本控制支持它,一个可能的解决scheme就是每当你做出这样的攻击的时候,从源头引入一个分支。 如果人们被鼓励避免在这些特殊的“完成”叉子内编码新特征,那么最终将更多的工作来将新特征与分叉相结合,而不是摆脱黑客行为。 然而更有可能的是,“好”的分叉将被抛弃。 如果你远离发布版,使得这样一个分支不实际(因为它不值得做上面提到的双重集成),那么你可能甚至不应该使用黑客。

一个非常理想的方法。

更现实的解决scheme是将程序分割成尽可能多的正交分量,并偶尔对某些组件进行完全重写。

更好的问题是为什么hacky解决scheme是不好的。 如果它不好,因为它会降低灵活性,那么直到需要灵活性时才会忽略它。 如果它不好,因为它影响程序的行为,忽略它,最终它将成为一个错误修复,将被解决。 如果因为看起来很丑而不好看,那么只要黑客已经本地化了就可以忽略它。

我曾经见过的一些解决scheme:

  • 在代码中注释HACK (或类似的scheme,如XXX
  • 有一个自动的报告运行和每周通过电子邮件发送给那些关心HACK评论出现次数的人
  • 在错误跟踪系统中添加一个新的条目,并附上正确的解决scheme的行号和描述(所以在写入黑客之前从研究中获得的知识不会丢失)
  • 编写一个testing案例,演示如何破解(如果可能的话),并检查到适当的testing套件(即使它抛出错误,最终人们将要清理)
  • 一旦黑客安装和压力closures,立即开始正确的解决scheme

这是一个很好的问题。 有一件事我注意到,因为我获得了更多的经验:黑客给你买了很短的时间,而且往往花费你更多的钱。 紧密相关的是“快速修复”,它解决了你所认为的问题 – 只有当它发生的时候才发现它根本不是问题。

抛开关于你是否应该这样做的争论,让我们假设你必须这样做。 现在的诀窍是尽量减less远距离的影响,以后很容易就把它扯下来,并且让自己变得讨厌,所以你记得去修复它。

令人讨厌的部分很容易:每次执行kludge时都会发出警告。

撕掉的部分可以很容易:我喜欢这样做是把一个子程序的名字背后的kludge。 由于您对代码进行了划分,因此更新更加容易。 当你得到永久的解决scheme时,你可以执行子程序,也可以不做任何操作。 有时候一个子类也可以很好地工作。 尽pipe如此,不要让别人依赖于你的快速修复。 没有看到情况就很难推荐任何特定的技术。

如果其他代码很好,最小化远程效果应该很容易。 总是通过发布的界面,等等。

尝试使商业伙伴清楚的破解成本。 然后他们可以做出明智的决定。

你可以故意写出过于严格和单独的方式,并要求修改重写。

我们必须这样做 – 做一个短期的演示版本,我们知道我们不想保留。 客户想要一个winTel盒子,所以我们在SGI / XWindows中开发了原型。 (我们都很stream利,所以这不是问题)。

自白:

我已经在C ++中使用'#define private public'来读取其他代码层的数据。 它作为黑客入侵,但运作良好,修复它从来没有成为一个优先事项。 现在是3年后…

黑客攻击的主要原因之一就是在修复黑客时引入新的错误的风险。 (特别是在处理TDD之前的代码库时)

我的答案与其他人有点不同。 我的经验是,以下做法可以帮助您保持敏捷,并从hackey第一次迭代/ alpha解决scheme转变为beta / production准备:

  1. testing驱动开发

  2. 小单元的重构

  3. 持续集成
  4. 良好的configurationpipe理
  5. 敏捷数据库技术/数据库重构

不言而喻,你必须得到利益相关方的支持才能正确地做到这些。 但是,通过这些产品,您可以拥有正确的工具和stream程,以自信的方式快速改变产品。 有时候你的改变能力是你处理变化风险的能力,从发展的angular度来看,这些工具/技术可以让你立足。