重构第三章:代码的坏味道

在这一章,我们会跟着“马先生”深入探讨代码中那些令人不安的坏味道,这些迹象提示着潜在的问题,可能都需要进行重构。我本身是个很爱干净的人,受不了一点儿坏代码的那种,以下是我整理的书中的一系列常见的坏味道及其对应的解决方法。

重复代码(Duplicated Code)
    坏味道: 同样的代码片段出现在不同的地方。
    解决方法: 提炼函数或方法,将重复的代码放入单独的函数中,然后在需要的地方调用该函数。

过长函数(Long Function)
    坏味道: 函数体过于庞大,难以理解。
    解决方法: 将长函数分解成多个小函数,每个函数负责一个明确的子任务。

大型类(Large Class)
    坏味道: 类的责任过多,代码难以理解和维护。
    解决方法: 将类分解为多个小类,每个类负责一个清晰的责任。

过长参数列表(Long Parameter List)
    坏味道: 函数的参数列表过长,难以调用和理解。
    解决方法: 使用对象封装参数,将相关的参数组织在一起,或者使用构造器模式。

发散式变化(Divergent Change)
    坏味道: 一处变化导致多个类需要修改。
    解决方法: 重新组织代码结构,确保每个变化只影响一个类,提高系统的灵活性。

散弹式修改(Shotgun Surgery)
    坏味道: 一次小修改需要在多个地方进行。
    解决方法: 将相关功能集中到一处,通过创建新的类或方法来避免修改的散布。

依恋情节(Feature Envy)
    坏味道: 一个类对另一个类的某些特性表现出过多的兴趣。
    解决方法: 将相关的功能移到数据所在的类中,提高代码的内聚性。

数据泥团(Data Clumps)
    坏味道: 一组数据经常一起出现。
    解决方法: 创建一个新的类,将这些相关的数据聚合在一起,提高代码的清晰度。

基本类型偏执(Primitive Obsession)
    坏味道: 过多使用基本数据类型而非创建新的类。
    解决方法: 引入新的类,提高代码的表达力和可读性。

开关语句(Switch Statements)
    坏味道: 使用开关语句会导致代码难以扩展。
    解决方法: 使用多态或者策略模式替代开关语句,提高代码的可维护性。

在这个过程中,我们发现了许多常见的问题,但这仅仅是冰山一角。为了使我们的代码更为清晰、可读,为进行重构奠定基础,下面这些也应该了解一下:

异曲同工的类(Parallel Inheritance Hierarchies)
    坏味道: 类的继承体系与另一组类的继承体系存在明显的相似性。
    解决方法: 通过重构,使两个继承体系保持一致,或者考虑合并它们为一个。

冗余类(Redundant Class)
    坏味道: 存在一个类,其行为和另一个类完全相同。
    解决方法: 将冗余类移除,直接使用现有类。

懒惰类(Lazy Class)
    坏味道: 有些类的责任相对较小,负担不够重。
    解决方法: 考虑将这些懒惰类与其他类合并,或者增加它们的责任。

纯稚的数据类(Data Class)
    坏味道: 一个类只包含数据而没有提供方法。
    解决方法: 考虑为数据类增加功能,或者将其与其他类合并。

过多解释性变量(Message Chains)
    坏味道: 通过一系列对象引用来获取最终想要的信息。
    解决方法: 创建中间对象,将这些链条断开,或者在适当的位置引入一个新方法。

中间人(Middle Man)
    坏味道: 一个类的大部分方法都委托给另一个类。
    解决方法: 直接调用被委托的类的方法,而不通过中间人。

不适当的依赖(Inappropriate Intimacy)
    坏味道: 两个类之间的关系过于紧密,不符合设计的松耦合原则。
    解决方法: 重新组织类之间的关系,确保它们之间的依赖是必要的。

异味注释(Comments)
    坏味道: 代码中包含过多或无效的注释。
    解决方法: 通过提高代码的自描述性和清晰度,减少对注释的依赖。

不完美的库类(Incomplete Library Class)
    坏味道: 类库中的某个类缺少必要的功能。
    解决方法: 添加缺失的功能,使得类库更加完备。

不良继承(Bad Inheritance)
    坏味道: 子类继承了父类的一些方法,却不需要或不适合。
    解决方法: 通过重构,调整继承关系,确保子类只继承其需要的方法。

过多的注释(Too Much Information)
    坏味道: 代码中包含大量详细的注释,过多的信息反而使得代码难以理解。
    解决方法: 简化代码结构,提高命名质量,减少注释的依赖。

意图不明确的元素(Speculative Generality)
    坏味道: 存在一些被设计得很通用,但实际上从未被使用的类或方法。
    解决方法: 移除未使用的通用元素,简化代码结构。

装饰者模式过度使用(Decoration Overuse)
    坏味道: 过度使用装饰者模式导致类的层次结构变得复杂。
    解决方法: 精简装饰者模式的使用,确保其结构清晰且易于理解。

新手程序员(Novice Programmer)
    坏味道: 代码中充斥着新手程序员常见的错误和不成熟的设计。
    解决方法: 通过培训和知识分享提高团队整体水平,进行代码审查以发现并纠正错误。

中途加入的类(Incomplete Library Class)
    坏味道: 类库中的某个类缺少必要的功能。
    解决方法: 添加缺失的功能,使得类库更加完备。

面条式代码(Spaghetti Code)
    坏味道: 代码结构复杂,难以理解,呈现出纷乱的、错综复杂的结构。
    解决方法: 通过模块化和重构,将复杂的代码结构简化为更清晰、可维护的形式。

巨大的类(Huge Class)
    坏味道: 类的代码量庞大,包含过多的属性和方法。
    解决方法: 将大类拆分成更小的、更具单一职责的类。

巨大的方法(Huge Method)
    坏味道: 单个方法的代码量庞大,难以理解。
    解决方法: 将大方法拆分成多个小方法,每个方法负责一个明确的子任务。

不当的引入(Inappropriate Intimacy)
    坏味道: 类之间的关系过于亲密,暴露了不应该知道的信息。
    解决方法: 通过修改关系或添加中间层,减少类之间的直接联系。

静态夸大其词(Exaggerated Use of Singleton)
    坏味道: 过度使用单例模式,导致程序过于依赖全局状态。
    解决方法: 谨慎使用单例模式,考虑使用依赖注入等替代方案。

失控的类(Uncontrolled Side Effect)
    坏味道: 类的某些方法引起的副作用无法被控制。
    解决方法: 通过重构,确保类的状态变化是可预测和可控的。

晦涩难懂的代码(Opaque Code)
    坏味道: 代码难以理解,缺乏清晰的逻辑结构。
    解决方法: 通过提高命名清晰度、拆分复杂表达式等手段,使代码更易读。

冗余的子类(Redundant Subclass)
    坏味道: 子类继承了父类的大部分行为,但只修改了一小部分。
    解决方法: 考虑将子类合并,通过配置或参数等方式实现不同的行为。

滥用继承(Inappropriate Inheritance)
    坏味道: 过度使用继承,导致继承关系变得复杂且难以理解。
    解决方法: 谨慎使用继承,优先考虑组合和接口。

希望你下次看见代码不知道好坏的时候可以来参照参照我这个文章,在进行代码重构的过程中,认识和解决这些坏味道将有助于提高代码质量、可读性和可维护性。同学们,快去检查一下自己的代码吧,也许正等着你的是一次精彩的重构之旅,跟打扫卫生一样舒服的那种~

我在这儿整理了几个味道不对的代码,同学们快来瞅瞅,看一下是不是让你也想赶紧打扫它:

示例一:滥用继承(Inappropriate Inheritance)

class Animal {
    void eat() {
        System.out.println("Animal is eating.");
    }
}

class Dog extends Animal {
    void bark() {
        System.out.println("Dog is barking.");
    }
}

问题: 在这个例子中,Dog类继承了Animal类,但是Dog并不需要eat方法。这导致了继承关系的混淆,使得代码结构变得复杂。这里的坏味道是滥用继承。同学们应该注意到Dog类并不需要从Animal类继承,而更好的方式是通过组合或接口来实现需要的行为。你觉得嘞~~

示例二:过多解释性变量(Message Chains)

class Customer {
    private Address address;

    public Address getAddress() {
        return address;
    }
}

class Address {
    private Country country;

    public Country getCountry() {
        return country;
    }
}

class Country {
    private String name;

    public String getName() {
        return name;
    }
}

问题: 客户类通过一系列的方法调用才能获取国家名称,形成了冗长的消息链。这里的坏味道是过多解释性变量。读者应该注意到客户类访问国家名称的方式过于繁琐,可以通过引入新的方法或对象来简化这个过程。

示例三:晦涩难懂的代码(Opaque Code)

public int calculate(int x, int y) {
    return (x & y) + (x | y) - (x ^ y);
}

问题: 这个计算方法虽然看起来简单,但缺乏清晰的逻辑结构,难以理解其实际意义。这里的坏味道是晦涩难懂的代码。同学们应该注意到这个计算方法的目的不明确,可以通过更有意义的命名和拆分表达式来提高代码的可读性。

你可能感兴趣的:(团队合作优雅之道,重构)