重构手法——函数行为重塑类 | 函数签名 | 添加参数

70 阅读6分钟

简介

“Change Function Declaration - 更改函数声明 | Add Parameter - 添加参数”是一种重构手法,它主要用于在函数或方法中添加新的参数。当原有的函数或方法在执行过程中需要额外的信息来完成其功能,而这些信息当前没有通过参数传递时,就可以使用此技术。添加参数可以使函数或方法更加灵活和通用,以适应更多的使用场景,同时有助于提高代码的可维护性和可扩展性。

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

  • 函数或方法需要额外信息:当函数内部的逻辑需要更多的信息才能正确完成其功能,但这些信息没有通过参数传递,可能导致函数使用一些全局变量或硬编码的值,影响代码的可维护性和可测试性。
  • 函数功能扩展:当需要扩展函数的功能,但原有的参数无法满足需求时,需要添加新的参数来支持新功能。

Add Parameter 的详细步骤

  1. 确定添加参数的必要性
    • 分析函数或方法的功能:仔细检查函数的内部逻辑,确定哪些额外的信息是完成该功能所必需的,但当前未作为参数传入。
    • 考虑函数的通用性:思考添加新参数是否会使函数在更多场景下可用,而不仅仅是满足当前需求。
  2. 选择参数的类型和名称
    • 选择合适的参数类型:根据需要传递的信息,确定新参数的数据类型。例如,如果需要传递一个数字,可能是 intdouble 等;如果是对象,选择相应的对象类型。
    • 选择具有描述性的名称:为新参数取一个能够清晰描述其用途的名称,避免使用模糊或无意义的名称,如 param1arg2 等。
  3. 修改函数或方法的声明
    • 在函数或方法的参数列表中添加新参数:将新参数添加到适当的位置,注意参数顺序的合理性,一般将相关的参数放在一起。
    • 确保函数或方法的签名更新:在函数或方法的声明处添加新参数,包括参数类型和名称。
  4. 调整函数或方法的内部实现
    • 在函数或方法内部使用新参数:根据新参数的用途,修改函数内部的逻辑,使其使用新添加的参数。
    • 确保函数的逻辑正确性:添加新参数后,重新检查函数的逻辑,确保它在各种情况下都能正确运行。
  5. 更新函数或方法的调用处
    • 在调用该函数或方法的地方添加新参数:在所有调用该函数或方法的位置,添加新的参数,传递相应的值。
    • 确保传递正确的值:传递的值应与新参数的类型和用途相匹配,避免类型不匹配或传递错误的值。
  6. 测试
    • 编译代码:确保代码编译通过,没有任何语法错误。
    • 运行测试:运行现有的单元测试,确保添加参数的操作没有引入新的错误。如果没有单元测试,编写相应的测试用例进行测试。
    • 手动测试:对于涉及用户界面或外部系统交互的函数,进行手动测试,确保功能的正确性。
  7. 代码审查
    • 同行评审:请同事或其他团队成员审查代码,确保添加参数的操作符合代码质量和可维护性标准。
    • 文档更新:如果有相关的文档,更新文档中关于该函数或方法的描述,包括新添加的参数及其作用。

示例

假设我们有一个简单的 Java 类,其中包含一个打印消息的方法,但现在我们想添加一个新的参数来控制消息是否为大写。

public class MessagePrinter {
    public void printMessage(String message) {
        System.out.println(message);
    }
}

以下是使用“Add Parameter”技术的步骤:

  1. 确定添加参数的必要性:

    • 我们希望添加一个参数来控制消息是否为大写,以提供更多的灵活性。
  2. 选择参数的类型和名称:

    • 选择 boolean 类型,名称为 uppercase,因为它只需要表示是或否的信息。
  3. 修改函数或方法的声明:

    • 将新参数添加到 printMessage 方法的参数列表中。
      public class MessagePrinter {
        public void printMessage(String message, boolean uppercase) {
        // 函数内部逻辑将根据 uppercase 参数进行修改
        }
      }
      
  4. 调整函数或方法的内部实现:

    • 根据 uppercase 参数修改函数内部逻辑,将消息转换为大写(如果 uppercasetrue)。
    public class MessagePrinter {
       public void printMessage(String message, boolean uppercase) {
          if (uppercase) {
             message = message.toUpperCase();
          }
          System.out.println(message);
       }
    }
    
  5. 更新函数或方法的调用处:

    • 在调用 printMessage 的地方添加新参数。
      public class Main {
         public static void main(String[] args) {
            MessagePrinter printer = new MessagePrinter();
            printer.printMessage("Hello, World!", true);
         }
      }
      
  6. 测试:

    • 编译代码,确保代码编译通过。
    • 运行测试,确保消息能正确打印,并且根据 uppercase 参数的值正确转换为大写或保持原样。
    • 进行手动测试,检查不同 uppercase 值的情况。
  7. 代码审查:

    • 请同事检查代码,确保代码可读性和可维护性没有下降。
    • 更新文档,说明 printMessage 方法新增了 uppercase 参数,以及其对方法行为的影响。

练习

基础练习题

  1. 简单添加参数
    • 对于以下 Java 代码,在 calculateArea 方法中添加一个参数 shapeType,用于表示形状类型(如 "rectangle" 或 "circle" ),根据不同的形状类型使用不同的计算面积公式。

      public class AreaCalculator {
         public double calculateArea(double length, double width) {
            return length * width;
         }
      }
      
  2. 为现有方法添加参数
    • 对于以下 Java 代码,在 validateUser 方法中添加一个参数 minAge,用于验证用户年龄是否大于或等于 minAge

      public class UserValidator {
         public boolean validateUser(int age) {
            return age >= 18;
         }
      }
      

进阶练习题

  1. 多参数添加与逻辑调整
    • 在以下 Java 代码中,在 processData 方法中添加两个参数 minValuemaxValue,并修改函数内部逻辑,使它只处理 dataArray 中在 minValuemaxValue 之间的数据。
      import java.util.ArrayList;
      import java.util.List;
      
      public class DataProcessor {
         public List<Integer> processData(int[] dataArray) {
            List<Integer> result = new ArrayList<>();
            for (int num : dataArray) {
               result.add(num);
            }
            return result;
         }
      }
      
  2. 复杂逻辑添加参数
    • 对于以下 Java 代码,在 calculatePrice 方法中添加一个参数 discountCode,根据不同的 discountCode 应用不同的折扣逻辑。

      public class PriceCalculator {
         public double calculatePrice(double basePrice) {
            return basePrice * 1.1;
         }
      }
      

综合拓展练习题

  1. 多模块添加参数

    • 考虑一个 Java 订单系统,包含 OrderServiceProductService 类。在 OrderService 类的 placeOrder 方法中添加一个参数 priority,用于表示订单的优先级。在 ProductService 类的 getProduct 方法中添加一个参数 language,用于根据不同语言返回产品信息。

      public class OrderService {
         public void placeOrder(Product product, int quantity) {
            System.out.println("Placing order for " + quantity + " of " + product.getName());
         }
      }
      
      public class Product {
         private String name;
      
         public Product(String name) {
            this.name = name;
         }
      
         public String getName() {
            return name;
         }
      }
      
      public class ProductService {
         public Product getProduct(int productId) {
            System.out.println("Getting product with id: " + productId);
            return new Product("Sample Product");
         }
      }
      
  2. 代码审查模拟

    • 完成上述多模块添加参数的操作后,模拟一份代码审查报告,指出添加参数后的优点和可能存在的潜在问题。