重构?还是重写?

本文探讨了重构和重写的区别及应用场景。重构旨在逐步改进代码质量,而重写则涉及从头开始建立新系统。两者都可能导致混乱,但重写的影响更为深远。选择合适的方法对于保持代码的可维护性和系统的稳定性至关重要。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

\

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

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

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

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

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

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

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

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

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

\

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

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

查看英文原文:Refactor or Rewrite?

### Java 方法重构重写和重载的概念及用法 #### 一、方法重载 (Overloading) 方法重载指的是在一个类中定义多个同名的方法,但它们的参数列表(数量、类型或顺序)必须有所不同。这种方法增强了代的灵活性,使开发人员可以根据不同的需求调用适合的方法版本。 - **特点**: - 同一个类内的方法。 - 参数的数量、类型或顺序不同。 - 返回值类型可以不同,但这不是判断重载的主要依据[^2]。 - **示例**: ```java public class Calculator { public int add(int a, int b) { return a + b; } public double add(double a, double b) { return a + b; } } ``` 在这个例子中,`add` 方法被重载了两次,一次处理整数相加,另一次处理浮点数相加[^4]。 --- #### 二、方法重写 (Overriding) 方法重写发生在子类继承父类的情况下,子类提供了与父类方法名称相同、参数列表相同的实现。这是面向对象编程中多态性的体现之一。 - **特点**: - 发生在父子类之间。 - 方法签名完全一致(包括方法名、参数列表以及返回值类型)[^1]。 - 子类方法不能降低访问权限[^2]。 - 如果父类方法声明为 `final` 或 `private`,则无法被重写[^3]。 - **示例**: ```java class Parent { public void greet() { System.out.println("Hello from Parent"); } } class Child extends Parent { @Override public void greet() { System.out.println("Hello from Child"); } } ``` 在此案例中,`Child` 类重写了 `Parent` 的 `greet()` 方法[^3]。 --- #### 三、方法重构 (Refactoring) 方法重构是一种改进现有代的过程,目的是提高代质量、可读性和可维护性,同时保持原有功能不变。这是一种良好的编习惯,有助于长期项目的可持续发展。 - **目标**: - 提高代清晰度。 - 减少冗余代。 - 改善性能或结构。 - **常见形式**: - 修改变量或方法名称使其更具描述性。 - 将复杂逻辑拆分为更小的模块。 - 使用设计模式优化架构。 - **注意**:重构不会影响程序对外部的表现行为[^5]。 --- #### 四、三者的区别总结 | 特性 | 方法重载 | 方法重写 | 方法重构 | |---------------------|------------------------------|--------------------------------|----------------------------| | 所属关系 | 同一类内 | 父类与子类之间 | 单独作用于某段代 | | 是否改变方法签名 | 是 | 否 | 可能涉及局部改动 | | 对外可见性 | 影响当前类 | 影响整个继承体系 | 不影响外部使用者感知 | | 主要目的 | 增强接口易用性 | 实现多态 | 提升代质量和可维护性 | --- ### 结论 掌握方法重载、重写重构的核心概念及其应用场景,可以帮助开发者写出更加优雅、高效易于维护的代。每种技术都有其独特的适用范围,在实际项目中需灵活运用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值