重构手法——数据重组类 | 数据完整性操作 | 封装记录

71 阅读4分钟

简介

“封装记录”(Encapsulate Record)是一种重构手法,主要用于处理数据记录(如简单的结构体或数据类)。当直接使用数据记录时,数据的访问和修改缺乏控制,容易导致数据的不一致性和代码的可维护性降低。通过封装记录,可以隐藏数据的实现细节,提供统一的访问和修改接口,增强代码的安全性和可维护性。

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

  • 数据直接暴露:记录中的数据字段直接被外部代码访问和修改,缺乏封装。
  • 缺乏数据验证:外部代码可以随意修改数据,没有对数据的有效性进行验证。
  • 代码耦合度高:外部代码依赖于记录的具体结构,当记录的结构发生变化时,需要修改大量的外部代码。

封装记录(Encapsulate Record)的详细步骤

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

示例

假设有一个简单的 Customer 记录,包含姓名和年龄字段,直接暴露给外部。

原始代码

public class Customer {
    public String name;
    public int age;
}

重构步骤

  1. 识别记录结构:Customer 类包含 nameage 字段,直接暴露给外部。
  2. 创建封装类:将字段声明为私有。
  3. 提供访问方法:为 nameage 字段提供 gettersetter 方法,并在 setter 方法中添加数据验证逻辑。
  4. 替换原始记录使用:将所有直接访问 nameage 字段的代码替换为调用 gettersetter 方法。

重构后代码

public class Customer {
    private String name;
    private int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        if (name != null && !name.isEmpty()) {
            this.name = name;
        } else {
            throw new IllegalArgumentException("Name cannot be null or empty.");
        }
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        if (age >= 0) {
            this.age = age;
        } else {
            throw new IllegalArgumentException("Age cannot be negative.");
        }
    }
}

练习

基础练习题

  1. 简单记录封装

    • 给定以下 Java 代码,Product 类包含 nameprice 字段,直接暴露。请封装该记录。

        public class Product {
          public String name;
          public double price;
      }
      
  2. 多字段记录封装

    • 下面的 Java 代码中,Employee 类包含 nameagesalary 字段,直接暴露。请封装该记录。
      public class Employee {
    public String name;
    public int age;
    public double salary;
}

进阶练习题

  1. 记录封装与复杂验证逻辑

    • 在这段 Java 代码中,User 类包含 emailpassword 字段,直接暴露。要求封装该记录,并在设置 email 时验证其格式,设置 password 时确保其长度不小于 6 位。

            public class User {
          public String email;
          public String password;
      }
      
  2. 记录封装与业务逻辑关联

    • 给定以下 Java 代码,Order 类包含 productquantitytotalPrice 字段,直接暴露。请封装该记录,并在设置 quantity 时更新 totalPrice(假设 product 的价格已知)。
      class Product {
    private double price;

    public Product(double price) {
        this.price = price;
    }

    public double getPrice() {
        return price;
    }
}

public class Order {
    public Product product;
    public int quantity;
    public double totalPrice;
}

综合拓展练习题

  1. 多记录封装与代码审查模拟
    • 考虑一个简单的 Java 图书馆系统,有 Book 类和 BorrowRecord 类。Book 类包含 titleauthorisAvailable 字段,BorrowRecord 类包含 bookborrowerborrowDate 字段,这些字段都直接暴露。请对这些记录进行 “封装记录” 重构。

    • 假设你完成了重构,请模拟一份简单的代码审查报告,指出重构后的优点和可能存在的潜在问题。

        import java.util.Date;
      
      public class Book {
          public String title;
          public String author;
          public boolean isAvailable;
      }
      
      public class BorrowRecord {
          public Book book;
          public String borrower;
          public Date borrowDate;
      }