停下来重构?
作者 Amr Elssamadisy 译者 金明 发布于 2009年6月23日 上午8时56分
Agile
主题
交付价值,
设计
标签
重构
Joshua Kerievsky在Yahoo!上的Refactoring小组里面发表了下面的帖子,引发了激烈讨论:
最近几年,我听到有一些人说只有在开发用户故事的时候才能重构。我从来都不赞同这个说法,因为我觉得有的情况只需要偿还技术债。最近几天,我和同事们重构了一下我们电子教学系统的代码。这并不是由用户故事驱动的。只是我们欠下了足够多的技术债,再也无法忍受,而现在是还债的好时候。系统中原来有一个邪恶的单例类,是系统代码中的核心角色。我们现在正在清除这个类,这样可以改善更多的代码设计。这工作感觉真棒。它让我们处在了一个有利的位置,将来开发用户故事就更容易了。
与此同时,我们继续每周交付一次——少量的bug修复和大量的重构。一如既往地,自动化的“微测试”和故事测试给我们大量的自信和勇气。无论如何,我觉得有必要分享这个经历,或许能引起一些有趣的讨论。
Dale Emery试图弄清楚Josh的问题场景:
Dale:我怀疑业界的普遍意见是不提倡技术人员介入业务决策。在决定偿还债务之前,决策者对业务和技术风险都需要有深刻的理解。如果缺乏足够的理解,决策者的决定就是不可靠的。你的例子很特殊,其中这样的风险很少。
Josh:是的,我们的例子的确特殊。但是,我认为通常情况下,让业务人员和技术人员在一起紧密工作是非常好的事情。这样,大家都能共同做出关于技术债的决定。当然,我们也不希望在大规模的项目里面,开发人员不跟其他人商量,就自行决定花上几个礼拜的时间来重构。
Dale:我认为(如果我假设错了,欢迎指正),你的客户拥有很强的技术背景,而且,至少绝大部分技术人员深刻理解了你们的业务。更进一步讲,你们自己就是你们的客户。当你们决定偿还技术债务的时候,你们非常清楚这样做给业务带来的影响,而且很可能恰恰是(因为)你对业务影响有足够的了解。
Josh:是的,之所以决定去重构清除技术债务,是因为
- 时机—— 我们刚刚给最大的客户完成了一个非常重要的发布,该短暂地走下“特性列车”了。
- 未来—— 更多的特性在等着我们,已有的开发经验告诉我们现在的技术债会拖慢前进的步伐。
- 通用语言—— 我们在代码中有一个很美妙的音乐隐喻.....但是,一些旧隐喻(书籍)的残余部分还分散在各处。
弄明白了Josh的问题场景(以及整个主题的其他内容),Adam Sokra提出:
你们的迭代时间长度不固定,从事增量式开发,而且尽可能频繁地发布。有时,你们有一组用户故事等待开发,并会设法尽快交付给客户。其他时候,你们就只用努力改善现有的设计。你们既是客户,也是开发人员。
这听起来就像是我曾经遇到过的每一个愉快的开源项目,与Scrum或者XP项目没多大关系。我不认为你们做错了什么,但是对那些试图弄明白敏捷环境下如何重构的人们来说,我不能肯定这有多大帮助。
不懂技术的业务人员有需求,技术团队也有需求,而我们就得在这二者之间博弈,这也是Scrum和XP的核心概念之。我们希望确保技术问题被熟练地解决,我们也希望业务人员可以最大程度地把握开发什么与何时开发的问题。
在你所描述的环境里面并不存在这样的对立关系。你们可以自由决定添加哪些特性,什么时候添加,什么时候暂停交付、转而关注于纯技术问题。
因此Adam提出Josh的环境并不适合于大多数的项目,最重要的差别在于:在Josh的项目里面,技术/非技术人员之间在沟通、理解和优先级等方面不存在矛盾。
Ron Jeffries认为项目中该进行的重构的多少是由业务决定的。毕竟,重构是一种投资,无法在短期内看到价值。他也反对在“不重构”和“停下来重构”之间做二元选择:
有一个假设需要指出,这就是:有些时候,最好是停下或者减缓“前进”的步伐进行清理。
对于很多人而言,这样的事情总是顺理成章:代码太糟糕了,只能停下或者延缓特性开发的进度,对代码进行清理。
对我可不是这样。这些说法缺乏连贯性。在清理代码的时候,我们为之付出的努力只有在将来才能受益。有些可能明天就产生回报,有些可能几个星期、几个月也没有回报。从来就没有立即带来好处的情况。
所有延缓特性开发进度的重构工作都是对未来的投资。需要弄清楚的是:是否值得付出这样的投资,怎样的投资是确实值得付出的,以及何时做出这样的投资是值得的。
Ron继续就“何时进行重构才是值得付出的投资”这一问题提出了自己的看法:
何时重构更合适,为什么?未来有如此多的可能性,随着时间流逝,特性的业务价值会不断增长。下面描述了两种可能的方法:
1、不做重构。特性的业务价值增长得越来越慢,直至不再增加,甚至可能因为引入的错误超过了增加特性带来的好处而导致下滑。
2、停止开发特性,进行重构。短时间内,特性的价值不会增长。过了这段时间,其价值又开始重新增长。我们认为优化代码之后,特性价值的增长速度会快于以往,但还需要一些时间,才能赶上不做重构的情形下特性的价值增长状况。这之后,我们认为,我们又将跑在前面。
对比这两种方式,我们可以得出什么结论?首先,只有重构结束之后的某个时间,重构给特性增加的价值才能浮现出来。其次,为了弄清楚重构(增加的特性价值)在什么时候能超过(不做重构时的特性价值),我们需要一些数字:重构会花多长时间,它会如何影响开发速度?而且,多长时间之后代码又会再次变糟,又是什么导致这些数字回落?
停下来、重构、稍微落后于特性、专注于少量特性、不赶进度而是优化代码,如此循环往复,却从来不受益;这样的状况完全有可能。我们希望这不可能......然而,这只在人们都很高效、技艺纯熟的情况下才可能......这是我前面提到的要点之一:对于专家,你的建议是合适的。
但是,这两种结果只是说明“停下来重构”的方法可能是自讨苦吃。是否有其他更好的方法?答案是肯定的。
让我们假设存在“重构加速变量(Refactoring Accelerator,RA)”,在上面第一种“不重构”的情况下,RA是0.0。在第二种情况下,我们把它设成1.0,这是完全相反的另一个极端。如果RA值在两者之间,会发生什么?
首先,如果特征价值是RA的函数会怎么样?在0到1的某个范围(0<x<1),如果RA小于这个范围的某个值(x),特征价值的增长率始终是下降的。我们重构不够,代码质量不断恶化,我们失去的越来越多。而对于某个值x,如果RA=x,特征的增长就是一个稳定值。我们的开发不会加快,但也不会减慢,保持了之前已有的速度。
现在,如果我们设定RA>x,又会发生什么?我们开发是会更快,还是速度减慢?我们知道在RA=1.0的时候,开发速度确实是减慢的,减到了0(但是之后我们可以加速)。
答案取决于开发速度随代码洁净度变化的曲线。我们知道代码越洁净,带来的开发速度也就越高。而且,最开始的干净代码会带来超高比例的良性效应,而追求代码尽善尽美到细枝末节,这样引发的良性效应则不会很多。
当RA稍微大于x的时候,可以得到更快的特性开发进度:我坚信这个是可能的,而且也不存在确切的不可能证据。如果确实如此,这种策略交付的价值会显著大于“停下来重构”的策略。
因此,如果这是对的——我也非常确信它的正确性,那么对于已经精通重构的团队来说,“停下来重构”策略从来就不是最佳策略。
Ron这里提出的要点是“停下来重构”从来不是擅长重构的团队应该选择的最佳策略。
这篇报道比较长,却只是那篇非常有趣的讨论的节选。在讨论之初,Josh介绍的并不是一个新问题。实际上,笔者在两年前就写过相应的社评“重构是必要的浪费”,而且InfoQ上面也经常会出现关于重构的讨论。整个社区在这个问题上依旧没有达成共识。
查看英文原文:Stop and Refactor?
分享到:
相关推荐
如何退出:如果鼠标点击频率过快无法停下来,请先让程序窗口到前台(ALT+TAB),然后按 ALT+F4 关闭程序。 软件无法被点击:尝试以管理员身份运行此软件。 注意热键冲突:设置热键时,留意是否会和其他程序冲突。
java笔试题算法介绍 坏消息是:你雇佣的新开发人员写了一些糟糕的、残暴的代码。 没有人能理解它的作用。 好消息:至少有单元测试来证明代码是有效的。 您的工作是重构代码并使...当你觉得代码足够好时,你可以停下来,
setup script 语法糖的应用使用单元测试提高开发效率设计模式的应用策略模式工厂模式重构技巧 (写出好代码 )Tasking单机用户进入游戏的时候可以看到游戏开始页面用户点击 startGame 可以开始游戏用户在开始游戏的...
我为什么要停下来? -好吧,因为我既没有时间也没有动力。 还没有完成,但是只要我能够继续,就可以。 我真的很乐意听到您的意见或改进建议。 :beaming_face_with_smiling_eyes: 在上检查结果 语言能力 ReactJS-...
7.9 停下来重构:cargo聚合的另一种设计 129 7.10 运输模型中的模块 131 7.11 引入新特性:配额检查 133 7.11.1 连接两个系统 134 7.11.2 改进模型:划分业务 135 7.11.3 性能调整 137 7.12 小结 137 第ⅲ...
7.9 停下来重构:cargo聚合的另一种设计 129 7.10 运输模型中的模块 131 7.11 引入新特性:配额检查 133 7.11.1 连接两个系统 134 7.11.2 改进模型:划分业务 135 7.11.3 性能调整 137 7.12 小结 137 第ⅲ...
在此处玩游戏: : ... 可以通过点击/单击将鸡停下来,再次点击/单击以继续走动。 可以使鸡朝着他们走动的方向滑动/拖动来奔跑。 当鸡被击中时,游戏结束。 点击玩!去做 重构 音效和音乐 游戏内教学 像素样式字体
- `F6`: 单步过,如果当前行是方法调用,会执行完该方法再停下来。 - `F7`: 单步返回,跳出当前方法,回到调用者。 - `F8`: 继续执行,直到遇到下一个断点或程序结束。 - `Shift + F5`: 结束调试会话。 5. **...
在车站内,当火车停下来时,乘客会下车并进入火车车厢。 乘客将在车站接车并在目的地车站接车。 火车的每节车厢最多可容纳 40 名乘客。 每列火车由若干节车厢组成。 ##指示 在你的机器上克隆 repo: $ git ...
在IT学习中,遇到困难时停下来深入思考,理解问题的本质,往往比盲目前行更有价值。这强调了反思和深度学习的重要性。 标签“课件”提示我们这是一个教育或学习相关的场景。在IT学习中,利用课件、教程、在线课程等...
我们的视线并不是固定在每一个字上,而是快速地扫过文本,只有当遇到不熟悉或异常的信息时,才会停下来仔细阅读。一般来说,中文阅读者在扫视过程中,一次性处理的汉字数量大约是3到4个,这与英文阅读者一次性处理4...
在车站内,当火车停下来时,乘客会下车并进入火车车厢。 乘客将在车站接车并在目的地车站接车。 一列火车的每节车厢最多可容纳 40 名乘客。 每列火车由若干节车厢组成。 奖励 - 添加一个收费系统,如果他们的...
例如,“尽管他试图把车子停下来,但还是没能避免一场车祸。” - **方式状语从句**:如“Do as I do.”,遵循“照做”的原则。 - **好像状语从句**:`as if`引导的从句通常需要将时态向过去推一格。例如,“She ...
在调试过程中,如果不想停下来检查某个断点,可以使用 F8 跳过它。 #### 四、复制与粘贴类快捷键 **1. Ctrl+C** 复制选中的文本。 **2. Ctrl+X** 剪切选中的文本。 **3. Ctrl+V** 粘贴剪贴板中的内容。 **4. ...
FPGA是一种可重构的硬件,具有高速处理能力和低功耗的特点,使其成为实现复杂算法的理想平台。在车牌识别中,FPGA可以快速执行图像预处理、特征提取和字符识别等任务,大大提高了系统的实时性和准确性。 首先,系统...
1 clone下来后运行创建名为myblog的数据库,并运行sql文件,修改jdbc.properties为自己的配置 2 修改七牛云配置为自己的配置 3 如遇到问题可联系我。。。 说明 这是我初学ssm框架写的代码,中间停了一段时间,后来再...
这一步通常利用小波分析的多分辨率特性,对图像进行分解和重构,以突出车牌的特征。小波分析能够有效地过滤噪声,提高图像清晰度,使得车牌区域更为突出。 2. **字符分割**:一旦车牌被成功提取,接下来是将车牌上...
6. **学习新概念**:遇到不懂的编程概念时,停下来学习并理解它。 通过FreeCodeCamp Bonfires,你不仅可以巩固JavaScript基础,还能培养解决问题的能力,这对任何编程职业都是宝贵的财富。随着你的进步,挑战会变得...