BT

如何利用碎片时间提升技术认知与能力? 点击获取答案

重构?还是重写?

| 作者 Vikas Hazrati 关注 0 他的粉丝 ,译者 侯伯薇 关注 0 他的粉丝 发布于 2009年11月29日. 估计阅读时间: 3 分钟 | GMTC大前端的下一站,PWA、Web框架、Node等最新最热的大前端话题邀你一起共同探讨。

重构和重写的目标,都是要通过提高的代码的可读性、结构和清晰性,从而提高系统的健壮性。清晰的代码更易于维护和改善。然而,在很多情况下,敏捷团队会难以在二者之间做出选择。

代码会随着时间的流逝变得越来越差,Michael Dubakov为此指出了下面的原因:

  • 越来越多的特性。它会导致复杂度的提升。
  • 捷径和权宜之道。为了支持诸如”我们在八月份需要这个NB的搜索,没二话”之类的特性
  • 开发者轮换。新的开发者根本不知道架构之后的所有起决定性作用的决定和主意。知识不可避免地随着人员的轮换而流失。
  • 开发团队的扩大。更多的人导致更少的交流,更少的交流产生糟糕的决定。

Michael 建议,虽然重构和重写都会使代码更加清晰,但是这两种技术都会导致现有系统的混乱。重构是一种增量式的活动,因此它每次只会接触到系统的一部分。这会在局部造成混乱,可能还比较容易控制。而另一方面,重写是更具有攻击性的改变,它会导致系统中更大的混乱。由于它会造成更广泛的影响,因此要想让重写的影响稳定下来,时间要比重构长得多。

我们重写旧的系统,因此混乱是家常便饭。在公开发行之后,混乱显著增长。我们预料会出现很多新的(和旧的)缺陷和古怪的行为,因此稳定期会更长

Peter Schuh认为团队经常会将两个词彼此替换使用,从而导致更多的迷惑和混乱。团队应该知道:和重构相比,重写更具有风险,因此应该恰当地使用术语。据他所说:

那只是语义上的。然而,在一些人受到伤害之前那只是语义上的。重写代码很有风险,并且有时会付出痛苦的努力,这么做不一定总有光明的结尾。如果我们执行重写,但是把它叫做重构,并且整个过程以梨形(指越到后来问题越多,需要付出的时间和成本也随之增长)进行,那就不会有业务人员停下来考虑语义了。他们只是会在下次听到重构这个词的时候退缩。

Guido A.J. Stevens 的想法很有趣,他认为问题并非出在重构和重写之间,而是在于:或者重构,或者重写并重构。他提出:即使当团队决定重写系统的时候,最终他们也会有两个系统并行运行。旧系统需要重构,而新系统正在被重写。这种组合变成了一项极度复杂的任务,据他所说:

维护老化的代码基础,并且编写新的系统,将会耗尽你的资源。你的团队被分割,并导致延迟。你需要制定计划,小心翼翼地执行转换。同时,你所面临的上市时间问题在你的竞争对手身上不存在,他们还会试图挖走你的客户。如果你能正视这种现实,并仍然想把公司前途押在重写上,那么你也许有机会成功。

Naresh Jain对于遗留代码有下面特别的的建议。当代码难于理解,并且团队不能确定它做什么的时候进行重构。当很清楚知道代码做什么,但是很难理解那些代码的时候就重写。

因此,重构是不断提升系统更好的方式。它是慢速前进的,通过小的、经常的提升来提高质量。重写也有其自身的优势,然而在很多情况下它是一种有风险的选择,并且团队可能永远都不确定产出物的情况。正如“Joel说软件”中所说:

重要的是要记住,当你从零开始的时候,没有绝对的理由相信你会比你第一次做得好。

查看英文原文:Refactor or Rewrite?

评价本文

专业度
风格

您好,朋友!

您需要 注册一个InfoQ账号 或者 才能进行评论。在您完成注册后还需要进行一些设置。

获得来自InfoQ的更多体验。

告诉我们您的想法

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

对于才开展系统而言,明显该重构 by Xu Yongrui

对新开发系统而言,重构应当是随时进行的,而不是代码累积到一定程度才开始,通过一次一小步和TDD方式,重构风险是很小的。

重构应该与多分支并行开发如影随行 by Tan Benjamin

1. 尤其是重构涉及到一些设计变更,或者影响面比较广的时候。
2. 项目在一些时间点上,始终应该有一段代码冻结的阶段。
3. 始终保持有一个立即可用的稳定版本分支。

重写在很多情况下,并不能得到光明的结局 by Jun Ran

Michael总结出来的导致代码混乱的四个原因,其中后3条并不会因为重写而得到改进,重写依然要面对权宜之计,人员流失,团队沟通等若干问题。

所以除非代码混乱和复杂到难以维系的地步,重写最好还是慎用。

风险决定,重写不应该和重构同级别讨论 by zhou xw

重构或者是重写,完全取决于风险,如果有些系统重构甚至比重写还麻烦,那就把系统遇到的问题列出进行解决然后重写,如果系统问题不是很大,重构是更好的选择,重构应该是随时都在进行,而重写则需要进行作出重大的决定,风险也是更大的。

具体而微 by 刘 显珂

我个人理解,无论是refactor和rewrite都是期望达到与原先同样的功能,也就是说完成refactor或者rewrite后,新的系统在可见的范围内与原系统是一样的。换句话说就是恒等变形。refactor是通过局部的变形来达到更好的可理解性,可维护性。rewrite也是如此。rewrite范围大很多,那么风险也自然大很多。
不过具体的代价取决于系统本身的复杂性,如果我们对用例掌握的非常好,那么风险仍然是可控,只是需要一定的时间。
问题的真正所在是我们为什要refactor或rewrite,同时我们又受到哪些条件的制约,比如:时间限制、竞争对手的行动,把这些结合起来考虑,才能想出合适的办法。
文章中提到的情况,我觉得很难推广的一般的情形。
最好是一开始就伴随重构,将问题消灭于无形。

如何保证风险? by ghost sole

问题在于不论是重构还是重写,如何保证风险?
需要重构或者重写的代码都是有些年月的代码,其中的一些潜规则不是理解代码就可以决定的,也不只靠TDD就可以保证的,必须了解用例的完整性、潜规则,系统和系统之间的契约,才能保证风险最小

Re: 对于才开展系统而言,明显该重构 by 侯 伯薇

记得重构那本书有个副标题,叫做改善既有代码的设计,随时进行的应该是针对局部代码的重构,而对于相关关联的代码的重构,似乎还是需要等到代码积累到一定程度的时候才能够进行,或者说到了做结合测试的时候,也要适当地做重构的工作。

Re: 重写在很多情况下,并不能得到光明的结局 by 侯 伯薇

在我的开发过程中,重写失败的原因主要都是在于重写的人对于原有的业务不是特别了解,特别是对于用户有特殊要求的程序,如果简单的凭借简单的了解而进行重写,很可能会忽略一些细节问题,而这些细节问题很可能会引起蝴蝶风暴,导致整个系统的问题。个人认为这这正是重写的风险所在。

Re: 重写在很多情况下,并不能得到光明的结局 by Jun Ran

你说得有道理。
我们也做过一些帮助客户重新开发系统的工作,也遇到了客户业务需求的整理和重新定义过程,这个过程中也发生了很多理解失误的问题,最后在超时超预算的情况下虽然完成了项目,但是综合起来很难说这是个成功的案例。
我感觉重写的复杂度跟重构相比要大了很多。

Re: 重写在很多情况下,并不能得到光明的结局 by 侯 伯薇

我也有同感,哈哈。
有时候,甚至就是在帮助客户重新编写一个功能的时候都是这样,因为里面有很多细节都是通过口头传达的,根本就没有显示在详细设计文档中,只有当初编写那个功能的人才了解。
解决这个问题,我想是否可以采用这样的方案,一种可能的方法是保证在代码中为这种细节的问题做比较详细的注释。另一种可能的方法是采用TDD的测试用例来保证。
不管怎样,其实都涉及到一个系统在开发过程中所涉及的行为规范(包括代码规范、维护规范、测试规范等等)的问题,只有大家都不是为了应付自己的问题来编写自己的代码,而是为了系统整体上的可维护性,才能够有好的结果吧。

重构还是重写与系统大小有关 by 曹 云飞

几万行代码的系统可能重写,几百万行代码的系统谁敢重写?在没有100%的掌握现有系统之前,重写的风险太大

Re: 重构还是重写与系统大小有关 by Jacky Li


几百万行代码的系统谁敢重写?

别说,还真见到不少团队重写的。

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

12 讨论

登陆InfoQ,与你最关心的话题互动。


找回密码....

Follow

关注你最喜爱的话题和作者

快速浏览网站内你所感兴趣话题的精选内容。

Like

内容自由定制

选择想要阅读的主题和喜爱的作者定制自己的新闻源。

Notifications

获取更新

设置通知机制以获取内容更新对您而言是否重要

BT