5代码整洁之道

格式化

代码格式

团队规则垂直格式水平格式

🎯 AI 时代的学习建议:不要只读理论。理解这一章的设计动机(为什么需要这个概念?)和边界条件(什么情况下会失效?)。当 AI 生成的代码涉及这些概念时,你能判断它是否用对了场景。AI 能帮你总结内容,但无法替代你亲手阅读、思考、建立直觉的过程。

第5章 格式化

一、导读

1.1 本章学习目标

第5章讲解了代码格式化的重要性。Uncle Bob 强调,代码格式不是个人偏好,而是团队协作的基础。本章的核心学习目标包括:

  • 理解团队规则的重要性:统一格式比个人偏好更重要。
  • 掌握垂直格式:相关代码应该靠近。
  • 理解水平格式:适当使用空格和缩进。
  • 学会保持适当的代码密度:行长度、空行使用。
  • 掌握团队约定的制定:使用格式化工具自动化。
  • 理解格式与可读性的关系:格式服务于可读性。

1.2 为什么本章如此重要

代码格式化看似琐碎,但它对团队协作有着深远影响。Uncle Bob 指出:统一的代码格式让代码库看起来像是一个人写的,这极大地提高了可读性和可维护性。

当团队成员使用不同的格式风格时,每次提交都会引入格式差异,导致代码审查时难以区分"真正的改动"和"格式改动"。

1.3 核心问题引导

你的团队有统一的代码格式规范吗?

格式不一致给协作带来了什么问题?

垂直格式(上下关系)和水平格式(左右关系)哪个更重要?

应该手动格式化还是使用工具?

格式规范应该多详细?


二、核心概念详解

2.1 团队规则

2.1.1 统一比正确更重要

Uncle Bob 强调:一个团队应该统一使用一种格式风格,即使你认为另一种风格更好。统一风格的价值远大于个人偏好。

java
// 团队规则示例
// 1. 使用2个空格缩进(不是4个空格,不是Tab)
// 2. 花括号不换行(K&R风格)
// 3. 行长度不超过100字符
// 4. 方法之间空一行
// 5. 运算符两侧加空格

2.1.2 使用格式化工具

bash
# Java: Google Java Format
google-java-format --replace src/**/*.java

# JavaScript/TypeScript: Prettier
prettier --write "src/**/*.{js,ts,tsx}"

# Python: Black
black src/

2.2 垂直格式

2.2.1 相关代码应该靠近

垂直距离应该反映代码的相关性。相关的代码应该放在一起。

java
// 差:相关代码分散
public class OrderService {
  private OrderRepository orderRepository;
  
  public void sendConfirmation(Order order) {
    // ...
  }
  
  private String customerName;
  
  public OrderResult processOrder(Order order) {
    // ...
  }
  
  private OrderRepository orderRepository; // 重复声明!
}

// 好:相关代码靠近
public class OrderService {
  // 字段放在一起
  private final OrderRepository orderRepository;
  private final EmailService emailService;
  private final String customerName;
  
  // 公共方法放在一起
  public OrderResult processOrder(Order order) {
    // ...
  }
  
  public void sendConfirmation(Order order) {
    // ...
  }
  
  // 私有方法放在一起
  private Money calculateTotal(Order order) {
    // ...
  }
}

2.2.2 变量声明靠近使用

java
// 差:变量声明远离使用
public void processOrder(Order order) {
  Money total;
  Money discount;
  Money tax;
  
  // ... 20行代码 ...
  
  total = calculateTotal(order);
  discount = calculateDiscount(order);
  tax = calculateTax(total, discount);
}

// 好:变量声明靠近使用
public void processOrder(Order order) {
  Money total = calculateTotal(order);
  Money discount = calculateDiscount(order);
  Money tax = calculateTax(total, discount);
}

2.3 水平格式

2.3.1 运算符两侧加空格

java
// 差:没有空格
private void addOrderItem(Order order,Item item,int quantity){
  order.getItems().add(item);
  order.setTotal(order.getTotal()+item.getPrice()*quantity);
}

// 好:适当的空格
private void addOrderItem(Order order, Item item, int quantity) {
  order.getItems().add(item);
  order.setTotal(order.getTotal() + item.getPrice() * quantity);
}

2.3.2 行长度限制

java
// 差:行太长
public OrderResult processOrder(Order order, Customer customer, PaymentMethod payment, ShippingAddress address, DiscountCode discount) {

// 好:合理换行
public OrderResult processOrder(Order order, 
                                Customer customer, 
                                PaymentMethod payment,
                                ShippingAddress address,
                                DiscountCode discount) {

2.4 代码密度

2.4.1 空行的使用

空行应该用于分隔逻辑上独立的代码块。

java
// 差:没有空行
public void processOrder(Order order) {
  validateOrder(order);
  Money total = calculateTotal(order);
  order.setTotal(total);
  repository.save(order);
  sendConfirmation(order);
}

// 好:适当的空行
public void processOrder(Order order) {
  validateOrder(order);
  
  Money total = calculateTotal(order);
  order.setTotal(total);
  
  repository.save(order);
  
  sendConfirmation(order);
}

三、实战案例

3.1 案例一:统一代码格式

java
// 改善前:格式混乱
public class OrderProcessor{
private OrderRepository repo;
public OrderProcessor(OrderRepository r){this.repo=r;}
public void process(Order o){
if(o==null)throw new IllegalArgumentException();
double t=0;
for(Item i:o.getItems()){t+=i.getPrice()*i.getQuantity();}
o.setTotal(t);
repo.save(o);
}
}

// 改善后:统一格式
public class OrderProcessor {
  private final OrderRepository repository;
  
  public OrderProcessor(OrderRepository repository) {
    this.repository = repository;
  }
  
  public void process(Order order) {
    if (order == null) {
      throw new IllegalArgumentException("Order must not be null");
    }
    
    Money total = calculateTotal(order);
    order.setTotal(total);
    
    repository.save(order);
  }
  
  private Money calculateTotal(Order order) {
    return order.getItems().stream()
        .map(item -> item.getPrice().multiply(item.getQuantity()))
        .reduce(Money.ZERO, Money::add);
  }
}

四、本章小结

第5章讲解了代码格式化的重要性,核心要点包括:

团队规则优先:统一格式比个人偏好更重要。

垂直格式:相关代码应该靠近,变量声明靠近使用。

水平格式:运算符两侧加空格,行长度合理。

代码密度:适当使用空行分隔逻辑块。

使用工具:用格式化工具自动化,避免手动争论。

Uncle Bob 的核心观点是:代码格式是团队协作的基础,统一格式让代码库像一个整体。


五、思考与练习

思考题

你的团队有统一的格式规范吗?如何执行?

格式不一致给协作带来了什么问题?

你使用什么格式化工具?

编程练习

为团队制定一份代码格式规范。

配置一个格式化工具(如 Prettier、Google Java Format)。

对一个格式混乱的文件进行格式化。

5/10格式化
0%