Ohhnews

分类导航

$ cd ..
foojay原文

AI时代编程语言的选择:为何冗长语言重获青睐?

#人工智能#编程语言#代码审查#软件工程#开发效率

目录


[LOADING...]

在架构评审、Slack 讨论串和会议走廊里,我不断听到同一个问题:

“如果代码是由 AI 编写的,编程语言还有意义吗?”

答案是:有,而且比以往任何时候都更重要——只是原因与过去十年我们争论的重点不同。

瓶颈已经转移

几十年来,我们一直在为开发者生产力进行优化。一个人写代码的速度有多快?语言的表达能力如何?我们发布功能的速度有多快?

这些逻辑现在已经行不通了。

AI 生成代码的速度超过了团队的审核速度

我观察到,一些团队在引入 Copilot 后,立即陷入了 PR(拉取请求)的海洋中。代码看起来合情合理,甚至能编译通过。但没有人有时间真正去验证它。现在的瓶颈已不再是编写代码,而是理解和验证代码。

为什么冗长的语言正在回归

我们曾经抱怨多年的语言——如 Java 和 C#——正在成为战略资产。并不是因为它们写起来更快(它们从未更快过),而是因为它们在压力下更容易阅读

当你在大规模审核 AI 生成的代码时,你需要:

  • 消除猜测的显式类型
  • 使不一致性显而易见的结构化模式
  • 审核员可以在几秒钟内确认的明确意图

样板代码现在成了“信号”

我们过去称之为“样板代码”(Boilerplate)的东西,现在成了关键信号。Java 方法签名会告诉你输入类型、返回类型和空值契约。你在阅读一行实现代码之前,就已经掌握了所有这些信息。而 Python 函数只会给你一个名称和一些可能代表任何东西的参数。

研究支持这一观点

Atlassian 在 ICSME'25 上发表了一项涵盖 118 名从业者和生产代码的研究。他们发现,81% 的开发者认为可读性仍然至关重要——即使是在 LLM(大语言模型)参与开发的情况下。最主要的动机是什么?降低长期维护成本。

他们还发现了一些更具体的内容:AI 生成的 TypeScript 和 Python 代码往往稍长且更难维护。而 Java、Kotlin、Go 和 Scala 生成的代码与人类编写的代码相比,差异微乎其微。

最后一点值得深思:AI 生成的 Java 代码看起来就像人类编写的 Java 代码,而 AI 生成的 Python 代码则会发生“漂移”。

这对实践意味着什么

  • 可读性不再是一种偏好,而是交付速度的关卡。
  • 冗长不再是一个缺陷,而是验证的加速器。
  • 清晰度决定了 AI 生成的代码能以多快的速度上线。

[LOADING...]

另一半:运行时性能

清晰度让代码通过审核,但一旦发布,它就必须运行。

基准测试说明了一切

来自 programming-language-benchmarks.vercel.app 的数据(2025 年 8 月,OpenJDK 21 对比 PyPy 3.11 对比 rustc 1.88):

基准测试JavaPython (PyPy)RustJava vs PythonRust vs Java
nbody (5M)446ms2,650ms163ms快 5.9 倍快 2.7 倍
nsieve (12)387ms2,403ms---快 6.2 倍---
fasta (2.5M)449ms2,215ms88ms快 4.9 倍快 5.1 倍
knucleotide (2.5M)1,059ms---219ms---快 4.8 倍
mandelbrot (5K)1,153ms---292ms---快 3.9 倍

在计算密集型工作中,Java 的运行速度比 Python 快 5-6 倍。Rust 则比 Java 快 2-5 倍。这并非合成的微基准测试,而是出现在实际后端系统中的算法负载。

Java 在性能堆栈中的位置

Java 处于一个务实的中间地带。它在紧凑循环中可能无法媲美 Rust,但它提供了强大的运行时性能,且无需手动内存管理。同时,它还配套了类型系统,使得 AI 生成的代码变得可审核。

从语言选择到流水线设计

真正的转变不在于选择“最好的语言”。软件生产现在有三个截然不同的阶段,每个阶段都有不同的优化标准:

AI 生成 -> 人类验证 -> 系统执行

第一阶段:生成

AI 受益于结构化、可预测的模式。具有强大惯例的语言留给它虚构创造性解决方案的空间更小。

第二阶段:验证

人类需要清晰度、强类型和明确的意图。这是 Java 和 C# 的优势所在。你可以快速扫描类型化的方法签名,并判断 AI 是否做对了。

第三阶段:执行

运行时性能、可扩展性和基础设施成本。Rust 和 C++ 在这里占据主导地位,而 Java 是大多数工作负载的有力中间地带。

以前这些是一个单一的决策,现在它们被解耦了。在一个阶段进行优化可能会损害其他阶段。

先求清晰,再求速度

我们不再需要在可读性和性能之间做选择,我们是在对它们进行排序。

  1. 清晰度第一 —— 如果审核员无法快速验证 AI 生成的代码,它就无法上线。世界上最快的代码如果卡在 PR 队列里,也是毫无用处的。
  2. 性能其次 —— 一旦部署,低效就会变成你的 AWS 账单。

代码示例:相同的意图,不同的审核体验

Python:简洁但模棱两可

$ python
def total_completed_orders(orders):
    return sum(order["total"] for order in orders if order["status"] == "COMPLETED")

简洁,但 orders 里有什么?"total" 是什么类型——float、int 还是 Decimal?如果键缺失了怎么办?审核员必须在脑海中处理所有这些不确定性。

Java:冗长但可验证

$ java
import java.math.BigDecimal;
import java.util.List;

public class OrderService {

    public BigDecimal totalCompletedOrders(List<Order> orders) {
        return orders.stream()
                .filter(order -> order.status() == OrderStatus.COMPLETED)
                .map(Order::total)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
    }
}

record Order(OrderStatus status, BigDecimal total) {}

enum OrderStatus {
    COMPLETED,
    PENDING,
    CANCELLED
}

代码确实更多,但审核员立即就能知道:输入是一个 List,总额是 BigDecimal(不是浮点数陷阱),状态是一个封闭的枚举。AI 无法在此处偷偷加入字符串比较或舍入错误。

Rust:最高保证,曲线陡峭

$ cargo
#[derive(PartialEq)]
enum OrderStatus {
    Completed,
    Pending,
    Cancelled,
}

struct Order {
    status: OrderStatus,
    total: f64,
}

fn total_completed_orders(orders: &[Order]) -> f64 {
    orders
        .iter()
        .filter(|order| order.status == OrderStatus::Completed)
        .map(|order| order.total)
        .sum()
}

强大的结构保证,且在这三者中拥有最好的运行时性能。代价是什么?更陡峭的学习曲线和所有权语义,这会减慢 AI 生成和人类审核的速度。

语言为何依然重要

语言比以往任何时候都重要——只是它不再是让你写代码更快的工具。

它的重要性在于作为 AI 输出与人类信任之间的接口。那些能够让验证变得廉价、让意图变得明显、让错误变得可见的语言,才是最终的赢家。

这就是语言依然重要的原因。