重构手法——数据重组类 | 数据完整性操作 | 用数据类替换记录

81 阅读4分钟

简介

“用数据类替换记录”(Replace Record with Data Class)是一种重构手法。在软件开发中,记录通常是简单的数据集合,缺乏行为和封装,可能导致代码的可维护性和扩展性较差。通过将记录替换为数据类,可以为数据添加行为和封装,使代码结构更加清晰,增强代码的可读性和可维护性。

针对的症状(代码坏味道)

  • 缺乏行为:记录仅仅是数据的简单集合,没有相关的行为方法,使得数据的处理逻辑分散在其他地方。
  • 低封装性:记录中的数据通常直接暴露,外部代码可以随意访问和修改,破坏了数据的完整性和安全性。
  • 代码复用性差:由于缺乏行为和封装,记录的数据处理逻辑难以复用,导致代码冗余。

用数据类替换记录(Replace Record with Data Class)的详细步骤

  1. 识别记录
    • 在代码中找出那些只是简单存储数据,没有行为方法的记录。这些记录通常是包含多个字段的结构体或简单类。
  2. 创建数据类
    • 为记录创建一个对应的新的数据类。
    • 将记录的字段复制到数据类中,并将其声明为私有。
  3. 提供访问方法
    • 为数据类的每个字段提供 getter 方法,用于获取字段的值。
    • 如果需要修改字段的值,为相应字段提供 setter 方法,并在 setter 方法中添加必要的数据验证逻辑。
  4. 迁移数据处理逻辑
    • 将原本分散在其他地方的与该记录相关的数据处理逻辑迁移到数据类中,作为数据类的行为方法。
  5. 替换原始记录的使用
    • 将所有使用原始记录的地方替换为使用新创建的数据类。
  6. 测试
    • 编译代码:确保代码编译通过,没有任何语法错误。
    • 运行测试:运行所有相关的单元测试,确保重构操作没有引入新的错误。
    • 手动测试:如果有必要,进行手动测试以验证功能的正确性。
  7. 代码审查
    • 同行评审:让同事或其他团队成员审查你的更改,确保代码质量和可维护性没有下降。
    • 文档更新:如果项目有维护文档的习惯,记得更新相关文档,说明用数据类替换记录的影响。

示例

假设有一个简单的 Address 记录,用于存储地址信息。

原始代码

public class AddressRecord {
    public String street;
    public String city;
    public String state;
    public String zipCode;
}

重构步骤

  1. 识别记录:AddressRecord 只是简单存储地址信息,没有行为方法。
  2. 创建数据类:创建 Address 数据类,将字段复制并声明为私有。
  3. 提供访问方法:为每个字段提供 gettersetter 方法。
  4. 迁移数据处理逻辑:假设原本有一个方法用于格式化地址,将其迁移到 Address 类中。
  5. 替换原始记录的使用:将所有使用 AddressRecord 的地方替换为使用 Address 类。

重构后代码

public class Address {
    private String street;
    private String city;
    private String state;
    private String zipCode;

    public Address(String street, String city, String state, String zipCode) {
        this.street = street;
        this.city = city;
        this.state = state;
        this.zipCode = zipCode;
    }

    public String getStreet() {
        return street;
    }

    public void setStreet(String street) {
        this.street = street;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    public String getState() {
        return state;
    }

    public void setState(String state) {
        this.state = state;
    }

    public String getZipCode() {
        return zipCode;
    }

    public void setZipCode(String zipCode) {
        this.zipCode = zipCode;
    }

    public String formatAddress() {
        return street + ", " + city + ", " + state + " " + zipCode;
    }
}

练习

基础练习题

  1. 简单记录替换

    • 给定以下 Java 代码,PersonRecord 是一个简单的记录,用于存储个人信息。请用数据类替换该记录。

        public class PersonRecord {
          public String name;
          public int age;
      }
      
  2. 多字段记录替换

    • 下面的 Java 代码中,EmployeeRecord 包含多个字段,用于存储员工信息。请用数据类替换该记录。
          public class EmployeeRecord {
        public String name;
        public int age;
        public String department;
        public double salary;
    }
    

进阶练习题

  1. 记录替换与复杂行为添加

    • 在这段 Java 代码中,ProductRecord 用于存储产品信息。要求用数据类替换该记录,并添加一个计算折扣后价格的行为方法。
          public class ProductRecord {
        public String name;
        public double price;
        public double discountRate;
    }
    
  2. 记录替换与数据验证

    • 给定以下 Java 代码,UserRecord 包含用户的邮箱和密码信息。请用数据类替换该记录,并在设置邮箱和密码时添加数据验证逻辑。
          public class UserRecord {
        public String email;
        public String password;
    }
    

综合拓展练习题

  1. 多记录替换与代码审查模拟

    • 考虑一个简单的 Java 电商系统,有 OrderRecordProductRecord 两个记录。OrderRecord 包含订单号、产品列表和总价,ProductRecord 包含产品名称、价格和库存数量。请用数据类替换这些记录,并将计算订单总价的逻辑迁移到 Order 数据类中。
    • 假设你完成了重构,请模拟一份简单的代码审查报告,指出重构后的优点和可能存在的潜在问题。
          import java.util.ArrayList;
    import java.util.List;
    
    public class ProductRecord {
        public String name;
        public double price;
        public int stock;
    }
    
    public class OrderRecord {
        public String orderNumber;
        public List<ProductRecord> products;
        public double totalPrice;
    }