返回

好方法应该有什么?剖析代码编写过程中容易忽略的“问题”

后端

方法设计的坏味道:避免可读性、可维护性和可扩展性差的方法

设计整洁、易于维护和可扩展的方法是编写健壮代码的基础。然而,有时我们的方法可能陷入不良的习惯,导致可读性、可维护性和可扩展性不佳。了解这些坏味道对于编写高质量的代码至关重要。

可读性差

长方法

过长的方法就像迷宫一样,难以导航。一般来说,一个方法应该少于 50 行代码。这样,代码更易于理解和维护。

// 坏
public void doSomething(int a, int b, int c, int d, int e, int f, int g) {
  // 冗长的代码...
}

// 好
public void doSomething(int a, int b) {
  // 简短、清晰的代码...
}

长参数列表

参数过多会让方法签名难以理解。尽量将参数列表限制在 5 个以内。如果需要更多参数,请考虑重构代码或使用数据传输对象 (DTO)。

// 坏
public void doSomething(int a, int b, int c, int d, int e, int f, int g) {
  // 冗长的代码...
}

// 好
public void doSomething(Person person) {
  // Person 类包含 a、b、c、d、e、f 和 g 属性...
}

重复代码

重复的代码是维护的噩梦。 DRY 原则 (Don't Repeat Yourself) 强调避免重复,以减少错误和提高可维护性。

// 坏
public void doSomething() {
  // 重复的代码...
}

public void doSomethingElse() {
  // 重复的代码...
}

// 好
public void doSomething() {
  // 一次性定义和使用代码...
}

判断逻辑嵌套

嵌套的判断逻辑会使代码难以理解和调试。尽量将判断保持在两层以内,并使用 switch 语句或 if/else if 结构进行嵌套。

// 坏
if (condition1) {
  if (condition2) {
    if (condition3) {
      // ...
    }
  }
}

// 好
switch (condition1) {
  case true:
    if (condition2) {
      if (condition3) {
        // ...
      }
    }
    break;
}

可维护性差

方法的功能不清晰

一个方法应该只做一件事。如果一个方法试图做太多的事情,它将变得难以理解和维护。遵循单一职责原则以确保方法专注于其主要职责。

// 坏
public void doSomething() {
  // 做很多不同的事情...
}

// 好
public void saveUser() {
  // 保存用户数据...
}

public void deleteUser() {
  // 删除用户数据...
}

方法的接口不友好

一个方法的接口应该清晰、易于使用。避免使用晦涩的名称或不必要的参数。遵循命名约定,并使用性的参数名称。

// 坏
public void calculate(int a, int b, int c) {
  // 计算...
}

// 好
public int calculateSum(int a, int b) {
  // 计算和返回总和...
}

方法的性能不够好

性能差的方法会影响应用程序的整体响应能力。使用适当的数据结构和算法,并避免不必要的计算。在必要时进行性能测试和优化。

// 坏
public void processList() {
  for (int i = 0; i < list.size(); i++) {
    // 耗时的操作...
  }
}

// 好
public void processList() {
  for (int element : list) {
    // 优化后的操作...
  }
}

方法的可靠性不够高

不可靠的方法可能会导致应用程序不稳定或崩溃。确保方法处理异常情况并返回正确的结果。使用异常处理和断言来提高可靠性。

// 坏
public void doSomething() {
  try {
    // ...
  } catch (Exception e) {
    // 不处理异常...
  }
}

// 好
public void doSomething() {
  try {
    // ...
  } catch (Exception e) {
    // 正确处理异常...
  }
}

可扩展性差

方法的耦合性太高

高耦合度使方法难以独立修改。遵循迪米特法则,只与直接依赖的方法通信。使用松散耦合机制,例如事件或消息队列。

// 坏
public void doSomething() {
  ClassA classA = new ClassA();
  ClassB classB = new ClassB();
  classA.doSomething();
  classB.doSomethingElse();
}

// 好
public void doSomething() {
  EventBroker eventBroker = new EventBroker();
  eventBroker.publishEvent(new Event());
}

方法的依赖性太强

强依赖性使方法难以移植或重用。使用抽象和接口来松散耦合方法,并尽量依赖于通用的库和框架。

// 坏
public void doSomething() {
  MySpecificLibrary library = new MySpecificLibrary();
  library.doSomething();
}

// 好
public void doSomething(Library library) {
  library.doSomething();
}

方法的扩展性不够好

扩展性差的方法难以适应变化的需求。遵循开放-封闭原则,对扩展开放,对修改封闭。使用设计模式,例如工厂方法或策略模式,来增强可扩展性。

// 坏
public class MyClass {
  public void doSomething() {
    // 硬编码逻辑...
  }
}

// 好
public abstract class MyClass {
  public void doSomething() {
    // 模板方法...
  }
}

public class MyClassImpl1 extends MyClass {
  // 实现 1...
}

public class MyClassImpl2 extends MyClass {
  // 实现 2...
}

避免坏味道

遵循以下原则可以避免方法设计中的坏味道:

  • 单一职责原则: 一个方法应该只做一件事。
  • 开放-封闭原则: 一个方法应该对扩展开放,对修改封闭。
  • 迪米特法则: 一个方法应该只与直接相关的其他方法通信。
  • 接口隔离原则: 一个方法的接口应该只包含调用者需要的方法。
  • 最少知识原则: 一个方法应该只依赖于它最少需要的信息。

通过遵循这些原则,我们可以设计出可读、可维护和可扩展的方法,提高代码质量,并提高团队协作效率。

常见问题解答

1. 如何判断一个方法太长?

一般来说,一个方法不应超过 50 行代码。如果超过此长度,则应考虑将其分解为较小的子方法。

2. 如何处理长参数列表?

尽量将参数列表限制在 5 个以内。如果需要更多参数,请考虑使用数据传输对象 (DTO) 或重构代码以减少参数数量。

3. 如何避免重复代码?

使用 DRY 原则,通过重构代码或使用提取方法等重构技术来消除重复的代码。

4. 如何提高方法的性能?

使用适当的数据结构和算法,避免不必要的计算,并在必要时进行性能测试和优化。

5. 如何增强方法的可靠性?

使用异常处理和断言来处理异常情况并返回正确的结果,以提高方法的可靠性。