面向人类和 LLM 的 Clean Code(不牺牲编码的乐趣)

发布: (2026年1月20日 GMT+8 03:56)
8 min read
原文: Dev.to

Source: Dev.to

(请提供您希望翻译的文章正文内容,我将根据您提供的文本进行简体中文翻译。)

对LLM友好的整洁代码

LLM 可以写代码。它们可以重构。它们可以生成测试。

如果你已经编码多年,很容易感到不安——不是因为工具不好,而是因为它触及了个人的东西:编码的乐趣很大一部分来自于巧妙。

  • 来自优雅的解决方案,来自看到问题坍缩为干净抽象的快感。
  • 然后你会读到这样的建议:“宁可无聊也不要聪明。”
  • 听起来像是对创造力的讣告。

事实并非一定如此。本文论证了两点:

  1. 面向人的整洁代码面向 LLM 的整洁代码 稍有不同(可读性 vs. 模型歧义)。
  2. 我们可以在不牺牲编码乐趣的前提下调和它们,只需把巧妙放在合适的位置。

上下文 vs. 预测

人类在有上下文的情况下阅读代码

  • 团队约定
  • 架构历史
  • 领域知识
  • 对“我们这里的做事方式”的直觉

LLM 没有这些上下文。
它们通过预测工作,而非意图。

因此 对 LLM 友好 的代码是指:

  • 最小化歧义
  • 拥有明确的契约
  • 结构上保持规律
  • 能安全地进行局部重构

不是 “为机器写代码”。
它是写能够经受重构的代码——无论是人类 还是 自动化的。

“为机器写代码”这个说法具有误导性,因为它暗示:

  • 巧妙是坏事
  • 优雅是危险的
  • 有趣是不专业的

但巧妙本身并不是敌人——错位的巧妙 才是问题。

两种巧妙

好的巧妙坏的巧妙
减少认知负荷将逻辑压缩进棘手的表达式
贴合领域模型利用语言的边缘案例
创建稳定的抽象依赖隐式假设
简化未来的变更看起来很炫但脆弱
工程艺术作者觉得有趣,其他人却痛苦

目标不是禁止巧妙——而是把它 放到正确的层次内部巧妙,外部平凡

调和方式

  • 面向人的整洁代码
  • 面向 LLM 的整洁代码
  • 构建美好事物的乐趣

只要我们让 外部 明确、稳定、可预测且易于重构,同时保持 内部 优雅、富有表现力且聚焦领域,这三者就可以共存。

示例

1️⃣ Ruby 服务,具有稳定的签名

class CreateOrder
  def self.call(input)
    new.call(input)
  end

  def call(input)
    input = Input.new(input)

    validate(input)
      .bind { persist(input) }
      .bind { publish_event(input) }
  end
end
  • 可预测的 .call
  • 显式的 输入强制转换
  • 清晰的 流程
  • 元编程

结果类型(巧妙实现)

class Result
  def self.ok(value = nil) = new(true, value, nil)
  def self.err(error)      = new(false, nil, error)

  attr_reader :value, :error

  def initialize(ok, value, error)
    @ok   = ok
    @value = value
    @error = error
  end

  def ok? = @ok

  def bind
    return self unless ok?
    yield(value)
  end
end

验证步骤

def validate(input)
  return Result.err(:missing_customer) if input.customer_id.nil?
  Result.ok(input)
end

面向领域、可组合的管道 → 人类通过组合获得优雅,LLM 获得显式契约和安全重构边界。

2️⃣ Go HTTP 处理器 – 显式且朴素

type Server struct {
    Orders *OrdersService
}

func (s *Server) CreateOrder(w http.ResponseWriter, r *http.Request) {
    var req CreateOrderRequest
    if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
        http.Error(w, "invalid json", http.StatusBadRequest)
        return
    }

    order, err := s.Orders.Create(r.Context(), req.ToInput())
    if err != nil {
        http.Error(w, err.Error(), http.StatusBadRequest)
        return
    }

    json.NewEncoder(w).Encode(order)
}

LLM 可以安全地重构此代码。

领域服务 – 乐趣所在

type OrdersService struct {
    Repo  OrdersRepo
    Clock Clock
}

func (s *OrdersService) Create(ctx context.Context, in CreateOrderInput) (*Order, error) {
    if err := in.Validate(); err != nil {
        return nil, err
    }

    order := NewOrder(in.CustomerID, s.Clock.Now())
    order.AddItem(in.ItemID, in.Qty)

    if err := s.Repo.Save(ctx, order); err != nil {
        return nil, err
    }
    return order, nil
}

领域模型、不变式、高内聚 → IO 很乏味;领域是艺术。

3️⃣ TypeScript – 类型降低歧义

// Explicit domain result
type Result<T, E> =
  | { ok: true;  value: T }
  | { ok: false; error: E };

公共函数签名

export async function createOrder(
  input: CreateOrderInput
): Promise<Result<Order, { code: string }>> {
  if (!input.customerId) {
    return { ok: false, error: { code: "MISSING_CUSTOMER" } };
  }

  const order = buildOrder(input);
  await repo.save(order);

  return { ok: true, value: order };
}

显式、易于使用、难以误用,LLM 能轻松安全地扩展。

强类型领域模型

type Money = { currency: "PLN" | "EUR"; cents: number };

function addMoney(a: Money, b: Money): Money {
  if (a.currency !== b.currency) throw new Error("currency mismatch");
  return { currency: a.currency, cents: a.cents + b.cents };
}

强制不变式、最小化表面、强语义 → “优雅编码”。

实用标准,您可以采用

指南原因
Stable function signatures (keyword args / typed structs)保证 LLM 可以依赖的契约
Explicit outputs (Result, typed errors)消除歧义
Clean abstractions (small DSLs inside the module)将巧妙性局部化
Composition pipelines在不泄漏复杂性的情况下实现算法优雅
If you must use metaprogramming or DSLs:
• place them in dedicated folders/modules
• document WHY
防止脆弱技巧意外蔓延
Write tests like it’s a mini‑framework测试为人类 and LLM 提供安全网

不是 因为“短就是坏”,而是因为压缩的代码更难安全地修改。LLM 重构 结构,而不是 意图。DRY 是一条指南,而非信条。

TL;DR

  • Cleverness belongs inside – 在它能够建模领域、降低认知负荷并创建稳定抽象的地方。
  • Boring, explicit code belongs outside – 稳定的签名、清晰的契约、常规的结构。

当我们尊重这条边界时,我们会得到:

  • 代码对人类 and LLM 都易于导航,
  • 安全的重构能力,
  • 以及构建优美、创新解决方案的乐趣。

如果可以防止误解,请重复意图。

如果编程的乐趣来源于:

  • 手写每一行代码
  • 炫耀语法技巧
  • 把 10 个想法压缩到 1 行

…那么,是的,这部分会逐渐消退。

但更深层的乐趣仍在——并且会增长:

  • 建模领域
  • 设计 API
  • 创建抽象
  • 降低复杂度
  • 让系统具备弹性

LLM 并不会取代这些,它们只会放大这些乐趣。

“Prefer boring over clever” 是不完整的建议。

更好的说法是:

  • Prefer boring where change happens often.
  • Prefer clever where meaning lives.

或者,简洁地说:

Clever inside, boring outside.

这就是为人类准备的干净代码。

这就是为 LLM 准备的干净代码。

它让编程的乐趣得以持续。

Back to Blog

相关文章

阅读更多 »