大话西游体之解决无耻之首“冗余代码”版权声明

原创
小哥 3年前 (2022-12-26) 阅读数 28 #大杂烩

排在最前面的是重复的代码。为什么它如此臭名昭著?观众可以阅读“消除不良品味”系列的开篇文章“重构,企业应用程序的圣经”,这篇文章没有重复,只是引用了以下几点:

提示:代码中的所有内容都应该只出现一次,而且只能出现一次。

下面我们将讨论如何消除几个典型的重复代码,以及如何养成消除重复代码的习惯。

在同一类中重复

第一个是同一类中存在重复代码,这是最容易识别和最容易解决的。查看以下示例:

try {
    executorService.runTasks(...)
    timer.scheduleAtFixedRate(
        () => saveProgress(getProgress()),
        period, period
    )
} finally {
    executorService.shutdown()
    timer.cancel()
    saveProgress(getProgress())
}

saveProgress(getProgress()) 出现在两个可以通过的地方 提取方法 来解决。

try {
    executorService.runTasks(...)
    timer.scheduleAtFixedRate(
        () => persistProgress(),
        period, period
    )
} finally {
    executorService.shutdown()
    timer.cancel()
    persistProgress()
}

def persistProgress() {
    saveProgress(getProgress())
}

如果一个类是有数千行的超长类,那么即使在一个类中也很难识别重复项。这涉及到另一种不良口味“超长品类”,后续《消除不良口味》将有专门的文章来解决。

在同一类树下重复

第二种是在同一类树下的不同子类中重复,这比第一种更难识别。

class Child1 extends Parent {
    def run() {
        init()
        process()
    }
    ...
}

class Child2 extends Parent {
    def run() {
        process()
    }
    ...
}

可以通过 上移方法模板方法 将公共部分上移到公共父类。

class Parent {
    def run() { // 模板方法
        init()
        process()
    }

    def init() {}
    def process() //无函数体,等同于虚函数
}

class Child1 extends Parent {
    override def init() { ... }
    override def process() { ... }
}

class Child2 extends Parent {
    override def process() { ... }
}

在不相关的课堂上重复

第三个是在两个完全不相关的班级,如果不专门寻找,很难找到。

class App1 {
    val last3 = scores.sort().take(3)
}

class App2 {
    val last10 = scores.sort().take(10)
}

可以先 提取方法 ,然后 移动方法 到新班级,消除重复。

class App1 {
    val last3 = Seqs.lastN(scores, 3)
}

class App2 {
    val last10 = Seqs.lastN(scores, 10)
}

object Seqs { // 新建工具类
    def lastN[E](seq: Seq[E], n: Int)
        : Seq[E] = { // 返回值类型
        seq.sort().take(n)
    }
}

在上面的示例中,有两个类在业务中没有连接。

有可能存在业务联系,或者直接类似,这次应该是 提取公共基类 ,然后根据第二次重复进行重构。

细心的看官会发现,三种类型的重复有递进关系,离的越来越远,识别起来越来越难,解决起来也是。“在不相关的课堂上重复”可以通过重构转换成前两种,然后继续重构得以解决。

养成良好的编码习惯。

解决重复并不难,难的是找到重复。寻找重复并不难,难的是培养寻找重复的习惯。在编写代码完成功能之前,一个代码会习惯性地来回查看其他人是否已经完成了相关功能,以及我是否可以共享代码来完成我想做的事情,这很容易发现重复。

提示:如果你想移动一个点,首先要知道她周围的圆圈。

我不仅解决了重复问题,而且在一段时间后,我发现我对整个系统的理解在不知不觉中提高了很多。

事实上,这和做人是一样的。著名金融教练博多·谢弗在《小狗钱钱的爸爸》中 - 《教你实现财务自由》一书还强调:

你对未来的责任是不断把私人领域变成主导领域。

私人领域是生活中与我相关的领域,而主导领域直接或间接受到我的影响。当事情发生时,我们不能只扫门前的雪。我们需要积极参与,从被动变为主动。只有这样,我们才能有更多的机会,让我们变得越来越好。

总结

我希望你不仅学会了消除重复的技巧,还了解了文章中的两个重要提示。

  1. 所有内容都应该只在代码中出现一次,而且只能出现一次。
  2. 如果你想移动一个点,首先要知道她周围的圆圈。

关于示例代码的注释

如果你想谈论如何编写好代码,你必须以代码为例。然而,在手机屏幕上显示代码是一个大问题。为了确保可以清楚地阅读示例代码,一个代码做了一些权衡:

  1. 用片段突出重点,而不是完全可运行的代码。
  2. 语言用Scala因为她简单易懂

别以为你不明白Scala有压力,一个院子会利用她最平易近人的地方,别担心。

提示:Scala是JVM平台上的一种语言,具有简单和可扩展的特性,现在是非常流行的大数据处理框架。Spark就是用Scala开发、学习Scala这不会是一个损失。

推荐

解决第一个邪恶的“重复代码”

消除过长的方法

消除巨无霸类

答读者问

你的参数列表像蚯蚓一样恶心吗?

单一责任原则真的简单吗?

要查看“大话重构”系列文章,请访问YoyaProgrammer公共号码,单击 核心技术,点击 大话重构。

版权声明

所有资源都来源于爬虫采集,如有侵权请联系我们,我们将立即删除