如何避免写垃圾代码:Java篇

如何避免写垃圾代码:Java篇

引言

Linux和Git的创建者Linus Torvalds曾严厉批评了一位Meta工程师提交的代码,称其增加了"无意义的抽象"和"垃圾代码"。这一事件揭示了软件工程中的一个核心原则:优秀代码应该最小化认知负荷

在Java开发中,这一原则尤为重要。本文将通过具体示例,探讨如何在Java中避免编写"垃圾代码"。

1. 避免不必要的抽象

反例:过度封装

java 复制代码
// 垃圾代码:无意义的抽象
public class NumberHelper {
    public static int makeIntFromTwoShorts(short high, short low) {
        return (high << 16) | (low & 0xffff);
    }
}

// 使用方式
int result = NumberHelper.makeIntFromTwoShorts(highValue, lowValue);

正例:直接清晰的表达

java 复制代码
// 好代码:直接表达意图
int result = (highValue << 16) | (lowValue & 0xffff);

知识点:只有当抽象真正减少复杂性时才使用它。直接使用位操作比调用一个意义不明的辅助方法更清晰。

2. 减少上下文切换

反例:过度分散的逻辑

java 复制代码
// 垃圾代码:需要跨多个文件理解
public class OrderProcessor {
    public void processOrder(Order order) {
        if (ValidationHelper.isValid(order)) {
            PricingHelper.calculatePrice(order);
            InventoryHelper.updateInventory(order);
            NotificationHelper.sendConfirmation(order);
        }
    }
}

正例:保持逻辑局部性

java 复制代码
// 好代码:自包含的逻辑
public class OrderProcessor {
    public void processOrder(Order order) {
        if (isValid(order)) {
            calculatePrice(order);
            updateInventory(order);
            sendConfirmation(order);
        }
    }
    
    private boolean isValid(Order order) {
        return order != null && order.getItems() != null && !order.getItems().isEmpty();
    }
    
    private void calculatePrice(Order order) {
        // 直接计算价格的逻辑
        double total = order.getItems().stream()
            .mapToDouble(item -> item.getPrice() * item.getQuantity())
            .sum();
        order.setTotalPrice(total);
    }
    
    // 其他方法也保持在同一个类中
}

知识点:人类大脑的工作记忆有限(4-7个信息块)。保持相关代码在视觉上接近,减少文件间跳转,可以显著降低认知负荷。

3. 明智地对待DRY原则

反例:盲目遵循DRY

java 复制代码
// 垃圾代码:过度抽象导致困惑
public class StringHelper {
    public static String concatenateWithDelimiter(String str1, String str2, String delimiter) {
        return str1 + delimiter + str2;
    }
}

// 在代码中多处使用
String fullName = StringHelper.concatenateWithDelimiter(firstName, lastName, " ");
String address = StringHelper.concatenateWithDelimiter(street, city, ", ");

正例:适当重复以提高清晰度

java 复制代码
// 好代码:直接拼接更清晰
String fullName = firstName + " " + lastName;
String address = street + ", " + city;

知识点PRY(Please Repeat Yourself)原则有时比DRY更重要。简单的字符串拼接不需要抽象成辅助方法。

4. 命名即文档

反例:模糊的命名

java 复制代码
// 垃圾代码:命名没有提供有用信息
public class Helper {
    public static void processData(List<Object> data) {
        // 处理逻辑
    }
}

正例:清晰的命名

java 复制代码
// 好代码:命名准确描述功能
public class OrderValidator {
    public static void validateInventoryAvailability(List<OrderItem> orderItems) {
        // 验证逻辑
    }
}

知识点:Java开发者依赖IDE的自动完成和代码提示。好的命名可以减少查看方法实现的需要。

5. 谨慎使用设计模式

反例:模式滥用

java 复制代码
// 垃圾代码:过度工程化
public interface DataProcessor {
    void process();
}

public abstract class AbstractDataProcessor implements DataProcessor {
    // 多层抽象
}

public class ConcreteDataProcessor extends AbstractDataProcessor {
    @Override
    public void process() {
        // 实际处理逻辑
    }
}

// 还需要工厂类来创建实例

正例:简单直接的设计

java 复制代码
// 好代码:需要时再引入模式
public class DataProcessor {
    public void processData() {
        // 直接实现处理逻辑
    }
}

知识点:YAGNI原则(You Aren't Gonna Need It)------不要为未来可能需要的功能添加抽象,等到真正需要时再重构。

6. 适应AI编程新时代

随着AI编程助手(如GitHub Copilot、Amazon CodeWhisperer)的普及,代码的可预测性和局部性变得更加重要。

反例:AI不友好的代码

java 复制代码
// 垃圾代码:逻辑分散,AI难以理解完整上下文
public class Service {
    public void execute() {
        Helper.doSomething(this.data);
    }
}

// 在另一个文件中
public class Helper {
    public static void doSomething(Data data) {
        // 复杂的逻辑
        AnotherHelper.doMore(data);
    }
}

正例:AI友好的代码

java 复制代码
// 好代码:自包含的方法
public class Service {
    public void execute() {
        doSomethingWithData(data);
    }
    
    private void doSomethingWithData(Data data) {
        // 完整的逻辑在同一方法中
        validateData(data);
        processData(data);
        updateData(data);
    }
    
    private void validateData(Data data) {
        // 验证逻辑
    }
    
    private void processData(Data data) {
        // 处理逻辑
    }
    
    private void updateData(Data data) {
        // 更新逻辑
    }
}

知识点:AI工具的上下文窗口有限。保持相关代码在同一个上下文中,可以提高AI生成代码的质量。

7. 性能与可读性的平衡

反例:过度优化降低可读性

java 复制代码
// 垃圾代码:为了微小性能提升牺牲可读性
public class OptimizedCalculator {
    public static int calculate(int[] values) {
        int result = 0;
        for (int i = 0; i < values.length; i++) {
            result += values[i] * (i % 2 == 0 ? 2 : 3) + (i > 5 ? values[i] / 2 : 0);
        }
        return result;
    }
}

正例:清晰第一,优化第二

java 复制代码
// 好代码:清晰表达意图,必要时再优化
public class ClearCalculator {
    public static int calculate(int[] values) {
        int sum = 0;
        
        for (int i = 0; i < values.length; i++) {
            int multiplier = (i % 2 == 0) ? 2 : 3;
            int bonus = (i > 5) ? values[i] / 2 : 0;
            
            sum += values[i] * multiplier + bonus;
        }
        
        return sum;
    }
}

知识点:现代JVM的JIT编译器非常智能,通常能够优化清晰的代码。可读性差的代码反而可能阻碍编译器的优化能力。

总结:写好Java代码的关键原则

  1. 最小化认知负荷:让代码容易被人类和AI理解
  2. 保持局部性:相关代码保持接近,减少文件间跳转
  3. 命名即文档:使用清晰准确的命名表达意图
  4. 谨慎抽象:只在抽象真正减少复杂性时使用
  5. 适度重复:有时重复比错误的抽象更好
  6. 渐进复杂:需要时再引入模式,而不是预先过度设计
  7. 清晰优于巧妙:可读性比微小性能提升更重要

原文:xuanhu.info/projects/it...

相关推荐
hadage2332 分钟前
--- JavaScript 的一些常用语法总结 ---
java·前端·javascript
码一行2 分钟前
从0到1用Go撸一个AI应用?Eino框架让你效率翻倍!
后端·go
掘金一周14 分钟前
大部分人都错了!这才是chrome插件多脚本通信的正确姿势 | 掘金一周 11.27
前端·人工智能·后端
懂得节能嘛.16 分钟前
【Java动态线程池】Redis监控+动态调参
java·开发语言·redis
bcbnb18 分钟前
苹果App上架全流程指南:从注册到审核通过,一文读懂
后端
aiopencode18 分钟前
在 Windows 环境完成 iOS 上架,跨平台发布体系的落地实践
后端
疯狂的程序猴23 分钟前
Fiddler抓包配置与使用教程,HTTPHTTPS抓包、代理设置与接口调试完整指南
后端
豆奶特浓623 分钟前
Java面试模拟:当搞笑程序员谢飞机遇到电商秒杀与AIGC客服场景
java·spring boot·微服务·面试·aigc·高并发·电商
明洞日记25 分钟前
【设计模式手册013】命令模式 - 请求封装的优雅之道
java·设计模式·命令模式
方白羽33 分钟前
Android多层嵌套RecyclerView滚动
android·java·kotlin