什么是重构?什么是修改代码?

Dav*_*one 75 refactoring

我知道重构是"改变程序的结构,以便不改变功能".我正在与我在大学的最后一年项目中与我合作的一些人谈话,我很惊讶他们有更广泛的(因为想要更好的词)重构的观点.

我认为重构就像提取方法和重命名类一样.他们还建议之类的东西改变的数据结构(如Java的LinkedList一个ArrayList),改变算法(使用合并排序而不是冒泡排序的),甚至重写大量代码的重构.

我很确定他们错了,但我无法给出一个很好的理由,因为他们的建议确实改变了程序(并且可能使其更好)而不改变其行为.我是对的,更重要的是,为什么?

Mit*_*eat 70

Martin Fowler的"重构:改进现有代码的设计"或许是参考:

重构是一种用于改进现有代码库设计的受控技术.它的本质是应用一系列小的行为保持变换,每个变换"太小而不值得做".然而,这些变换中的每一个的累积效应是非常显着的.通过小步骤完成它们可以降低引入错误的风险.您还可以在执行重组时避免系统损坏 - 这允许您在较长时间内逐步重构系统.

重构与单元测试密切相关.在重构之前编写测试,然后在重构中有一个置信度(与测试的覆盖率成比例).

一个很好的参考是:有关重构的信息

  • 福勒的引用当然是相关的,是的,它与单元测试相辅相成......但是,这是否真的回答了问题:示例是否提到重构或只是修改代码?谁是对的,OP或他的同事,为什么? (13认同)

Car*_*ter 34

Fowler在代码更改之间绘制了一条简洁的界限,而不会影响其行为.他把那些没有的人称为"重构".这一个重要的区别,因为如果我们将我们的工作分为重构和非重构代码修改活动(Fowler称之为"戴着不同的帽子"),我们可以应用不同的,适合目标的技术.

如果我们正在进行重构或保留行为的代码修改:

  • 我们所有的单元测试都应该在修改之前和之后通过
  • 我们不需要修改任何测试,也不需要编写任何新测试
  • 我们希望在完成后能够使用更清晰的代码
  • 我们不期待新的行为

如果我们正在进行改变行为的代码修改:

  • 我们期待新的行为
  • 我们应该写新的测试
  • 我们完成后可能会得到更脏的代码(然后应该重构它)

如果我们忽略了这种区别,那么我们对任何特定代码修改任务的期望都会变得混乱和复杂,或者无论如何都比我们注意到它更加混乱和复杂.这就是为什么这个词及其含义很重要.

  • +1,确切地说.特别是你给出的理由; 混乱的期望.在写我自己的答案时,我记住了这一点,即使我没有把它整齐地写下来:) (3认同)

pet*_*hen 18

提出我的观点:

小的,增量的更改使代码处于比找到的状态更好的状态

肯定是: "化妆品"的变化与功能没有直接关系(即它不能作为变更请求收费).

绝对不会:重写大块明显违反了"小的,增量的"部分.重构通常用作重写的反面:不再重复,而是改进现有的重写.

绝对可能:取代数据结构和算法在某种程度上是一种边界情况.这里决定性的差异IMO是一个小步骤:​​准备好交付,准备好处理另一个案例.


示例:假设您有一个Report Randomizer模块,它通过使用向量来减慢速度.您已经分析过,矢量插入是瓶颈,但不幸的是,模块依赖于许多地方的连续内存,因此在使用列表时,事情会无声地破坏.

重写意味着将模块从头开始扔出建筑物更好更快,只需从旧建筑中挑选一些.或者编写一个新的核心,然后将其装入现有的对话框中.

重构将意味着采取小步骤删除指针算术,以便切换.也许你甚至创建一个包含指针算术的实用函数,用对该函数的调用替换直接指针操作,然后切换到迭代器,以便编译器抱怨仍然使用指针算术的地方,然后切换到a list,然后删除溃疡功能.


背后的想法是代码本身变得更糟.在修复错误和添加功能时,质量会以小步骤衰减 - 变量的含义会巧妙地改变,函数会获得一个额外的参数来打破隔离,循环会变得复杂等等.这些都不是真正的错误,你可以告诉行计数会使循环变得复杂,但是会损害可读性和维护性.

同样,更改变量名称或提取函数也不是他们自己的有形改进.但总而言之,他们对抗缓慢的侵蚀.

就像一块鹅卵石墙,每天都落在地上.每天,一个路人会把它捡起来并放回去.


Jon*_*nik 12

考虑到Martin Fowler的定义,

重构是一种规范的技术,用于重构现有的代码体,改变其内部结构而不改变其外部行为.

......我认为你显然是对的.

他们还建议改变数据结构(如Java LinkedList到ArrayList),改变算法(使用合并排序而不是冒泡排序),甚至重写大块代码作为重构.

将算法更快地更改为某种东西显然不是重构,因为外部行为已经改变了!(再说一次,如果效果永远不会引起注意,也许你可以称之为重构 - 并且还会过早优化.:-)

这是我的一个宠儿; 当人们使用sloppily这个术语时很烦人 - 我甚至遇到过一些人可能会随便使用重构进行基本上任何改变或修复.是的,这是一个时髦而酷炫的流行语,但是对于简单的旧术语,如改变,重写性能改进,没有任何问题.我们应该在适当的时候使用它们,并在您真正改进软件内部结构的情况下保留重构.特别是在开发团队中,使用通用语言准确地讨论您的工作很重要.

  • 我不确定使代码更快更符合外部行为的变化...... (2认同)
  • 是的,我明白你的观点,我想这取决于你从哪个角度看.:)无论如何,IMO,在编程时你应该注意你每时每刻都戴着哪个"帽子",即你究竟想要达到的目标.换句话说,在添加/修复功能,重构和优化(提高性能)时,您应该有意识地分开.IIRC,福勒也在他关于重构的权威书中谈到了这一点. (2认同)

cbp*_*cbp 8

我认为你是对的,但争论一个词的含义并不是特别有趣或富有成效.

  • 我通常同意这一点,但是当我们审阅我们编写的文档时,讨论就出现了,我认为当我们使用相同的单词时,我们谈论同样的事情是很好的. (5认同)

Dan*_*man 8

如果一段代码的接口发生了变化,那么我认为这不仅仅是重构.

重构的典型案例是

  • "哦,我所有的单元测试都运行了,但我认为我的代码可以变得更干净"
  • 将代码更改为更易读/更清晰/更有效
  • 重新运行单元测试(不更改测试)并检查它们是否仍然有效

这意味着重构一词与您正在讨论的界面有关.即你可以重构一个界面背后的代码,同时更广泛地改变另一个界面的代码(也许这种区别是你和你的同事之间的混淆?)


sup*_*cal 5

http://en.wikipedia.org/wiki/Code_refactoring

代码重构是在不修改其外部功能行为或现有功能的情况下改变计算机程序内部结构的过程,以改善软件的内部非功能特性,例如提高代码可读性、简化代码结构、改变代码坚持给定的编程范式、提高可维护性、提高性能或提高可扩展性。

我同意重构代码确实包括破坏现有代码。只要确保你有单元测试,这样你就不会引入任何错误,其余的代码会编译。使用 Resharper for C# 之类的重构工具使这变得如此简单!

  • 使代码更易于理解
  • 清理代码并使其更整洁
  • 删除代码!应删除多余的、未使用的代码和注释
  • 提高性能
  • 制作更通用的东西。从最简单的事情开始,然后重构它以使其更容易测试/隔离或通用,以便它可以通过多态以不同的方式工作
  • 保持代码干燥 - 不要重复自己,因此重构会话可能涉及采用一些重复的代码并将其重构为单个组件/类/模块。