概览
在软件开发过程中,代码的可读性和可维护性往往是衡量代码质量的重要指标。本文将介绍两个能够显著提升代码质量的设计原则:组合函数模式(Composed Method Pattern)和抽象层次一致性原则(Single Level of Abstraction Principle, SLAP),并通过实例说明如何在实际开发中应用这些原则。
组合函数模式
组合函数模式最早由 Kent Beck 在《Smalltalk Best Practice Patterns》一书中提出。这是一个简单易懂且实用的编程原则,能够对代码的可读性和可维护性产生立竿见影的效果。
组合函数模式要求:
- 所有公有函数(入口函数)应当读起来像一系列执行步骤的概要
- 具体实现细节应当封装在私有函数中
这种模式有助于保持代码精炼并易于复用。阅读这样的代码就像在看一本书,入口函数是目录,指向各自的私有函数,而具体内容则在私有函数中实现。
示例代码
不良实践:
public void processOrder(Order order) {
// 验证订单
if (order == null) {
throw new IllegalArgumentException("Order cannot be null");
}
if (order.getItems().isEmpty()) {
throw new IllegalArgumentException("Order must contain at least one item");
}
// 计算总价
double total = 0;
for (OrderItem item : order.getItems()) {
total += item.getPrice() * item.getQuantity();
}
// 应用折扣
if (total > 1000) {
total *= 0.9; // 10% 折扣
} else if (total > 500) {
total *= 0.95; // 5% 折扣
}
// 更新订单状态
order.setTotal(total);
order.setStatus(OrderStatus.PROCESSED);
orderRepository.save(order);
// 发送确认邮件
String message = "Your order #" + order.getId() + " has been processed. Total: $" + total;
emailService.sendEmail(order.getCustomerEmail(), "Order Confirmation", message);
}
良好实践(应用组合函数模式):
public void processOrder(Order order) {
validateOrder(order);
double total = calculateTotal(order);
total = applyDiscount(total);
updateOrderStatus(order, total);
sendConfirmationEmail(order, total);
}
private void validateOrder(Order order) {
if (order == null) {
throw new IllegalArgumentException("Order cannot be null");
}
if (order.getItems().isEmpty()) {
throw new IllegalArgumentException("Order must contain at least one item");
}
}
private double calculateTotal(Order order) {
double total = 0;
for (OrderItem item : order.getItems()) {
total += item.getPrice() * item.getQuantity();
}
return total;
}
private double applyDiscount(double total) {
if (total > 1000) {
return total * 0.9; // 10% 折扣
} else if (total > 500) {
return total * 0.95; // 5% 折扣
}
return total;
}
private void updateOrderStatus(Order order, double total) {
order.setTotal(total);
order.setStatus(OrderStatus.PROCESSED);
orderRepository.save(order);
}
private void sendConfirmationEmail(Order order, double total) {
String message = "Your order #" + order.getId() + " has been processed. Total: $" + total;
emailService.sendEmail(order.getCustomerEmail(), "Order Confirmation", message);
}
抽象层次一致性原则(SLAP)
抽象层次一致性原则与组合函数密切相关。它要求函数体中的内容必须在同一个抽象层次上。如果高层次抽象和底层细节杂糅在一起,代码会显得凌乱,难以理解。
按照组合函数和 SLAP 原则,我们应当:
- 在入口函数中只显示业务处理的主要步骤
- 通过私有方法封装具体实现细节
- 确保一个函数中的抽象在同一个水平上,避免高层抽象和实现细节混杂
代码金字塔结构
满足 SLAP 实际上是构筑了代码结构的金字塔。金字塔结构是一种自上而下的,符合人类思维逻辑的表达方式。在构筑金字塔的过程中,要求金字塔的每一层要属于同一个逻辑范畴、同一个抽象层次。
示例:
// 顶层抽象 - 业务流程
public void registerNewUser(UserRegistrationRequest request) {
User user = createUserFromRequest(request);
validateUser(user);
saveUser(user);
sendWelcomeEmail(user);
}
// 中层抽象 - 具体步骤
private User createUserFromRequest(UserRegistrationRequest request) {
User user = new User();
mapBasicInfo(user, request);
mapAddressInfo(user, request);
mapPreferences(user, request);
return user;
}
// 底层抽象 - 实现细节
private void mapBasicInfo(User user, UserRegistrationRequest request) {
user.setUsername(request.getUsername());
user.setEmail(request.getEmail());
user.setFirstName(request.getFirstName());
user.setLastName(request.getLastName());
// 其他基本信息映射
}
顺便吆喝一句,技术大厂[机遇][机遇],前后端测试捞人,待遇还可以
如何进行抽象
1. 寻找共性
抽象的过程是合并同类项、归并分类和寻找共性的过程。将有内在逻辑关系的事物放在一起,然后给这个分类进行命名,这个名字就代表了这组分类的抽象。
示例:重构重复代码
public void processCustomerA(Customer customer) {
System.out.println("Processing customer: " + customer.getName());
double discount = customer.getTotal() * 0.1;
customer.applyDiscount(discount);
notifyCustomer(customer);
}
public void processVipCustomer(Customer customer) {
System.out.println("Processing customer: " + customer.getName());
double discount = customer.getTotal() * 0.2;
customer.applyDiscount(discount);
notifyCustomer(customer);
}
// 抽象后的代码
public void processCustomer(Customer customer, double discountRate) {
System.out.println("Processing customer: " + customer.getName());
double discount = customer.getTotal() * discountRate;
customer.applyDiscount(discount);
notifyCustomer(customer);
}
public void processRegularCustomer(Customer customer) {
processCustomer(customer, 0.1);
}
public void processVipCustomer(Customer customer) {
processCustomer(customer, 0.2);
}
——转载自:Lvan


登录 或 注册 后才可以进行评论哦!
还没有评论,抢个沙发!