阅读视图

终于有人做了 Subagent,TRAE 国内版 SOLO 模式来了

一、

全世界最好的 AI 编程工具,我不知道。

但是,我知道全世界最卷的 AI 编程工具,那一定是 TRAE

为什么这么说?

AI 编程工具一般有三种产品形态。

(1)插件。最早的 AI 编程工具 GitHub Copilot 就是插件。

(2)IDE。插件受制于宿主软件,有些公司不甘束缚,就开始做专门的 AI 编程 IDE,比如 Cursor、亚马逊的 Kiro、谷歌的 AntiGravity。

(3)终端。还有一些公司,专门做基于终端(也就是命令行)的工具,比如 Claude Code、Codex CLI、Gemini CLI。

所有的 AI 编程工具,基本上都属于这三大类之一。但是 TRAE 居然三种产品形态都做了,同时属于这三类!

它最早是插件,后来做了独立的 IDE,现在居然有第三种产品形态:SOLO 模式

从插件到 IDE(国内版),我都是 TRAE 的用户。我没用国际版,原因很简单,因为国内版免费。

今年7月份,TRAE 的国际版开始内测 SOLO 模式,反响热烈,我就很心动。现在终于正式发布了,本月12日国际版正式推出 SOLO 模式,国内版也在25日上线,更棒的是完全免费。

今天就来说说,什么是 SOLO 模式,为什么它很重要。

或者说,到底是什么原因,让 TRAE 觉得一种产品形态还不够,不停添加其他形态?

对于一个程序员来说,这三种产品形态,怎么选择?哪一种更好?

二、

插件没什么好说的。它调用的是 IDE 的内部接口,如果你有现成 IDE 环境需要加入 AI 功能,就选择它。

IDE 相比插件,功能更强、性能更好、一体化程度更高,适合追求功能和性能的用户。

至于 IDE 与终端,可以参考我的上一篇文章。它们各有特点,不是替代关系,而是互补关系。

IDE 强在它集成的那些功能,比如自动补全、智能感知(intellisense),终端没有。

终端强在方便调用各种命令行工具,可以加入 CI/CD 流程,以及下面要介绍的 Subagent,这是 IDE 缺乏的。

这一次 TRAE 发布的 SOLO 模式,就引入了很多终端才有的功能,所以才单独做成一个模式,因为很难把这些功能加入 IDE 形态。

习惯了 IDE 的同学,或者在 IDE 与终端之间犹豫的同学,有必要了解一下 SOLO 模式,也许有你要的功能。

三、

这次引入的新功能之中,最值得一提的就是 Subagent

我的印象中,国内还没有其他厂家做过这个功能。如果你想用好 AI 编程,一定要知道它。

顾名思义,Subagent 就是次一级的 agent(智能体)。可以理解成,它是一个 AI 应用之中的子任务。也就是说,它可以把一个大的 AI 编程任务拆分成若干个小任务。

这特别适合大项目,你根据不同的任务或者子目录,建立相应的 Subagent。

它有几个显著的优点。

(1)并行执行。多个 Subagent 可以同时执行,你把它们放在后台,自己在前台做其他事情,这大大节省了时间。IDE 就做不到这一点,只能顺序执行,这是终端独有的一个极大优点。

(2)节省上下文。通常来说,每次执行 AI 任务,都会把整个仓库作为上下文,发给模型。Subagent 可以指定不同的上下文,或者限制上下文局限于某一个目录,因此就节省了上下文,降低了费用。

(3)重复使用。子任务本身也是一个智能体,可以跨项目使用,也可与他人共享,简化了工作流程。

(4)灵活权限。每个子任务可以设置不同的访问权限,从而可以做出适合不同等级成员使用的 Subagent。

总之,Subagent 非常实用,很多人不想使用 IDE,部分原因就是没有 Subagent。

四、

TRAE 这次的 SOLO 模式,一大亮点就是引入了 Subagent,用它实现了多任务并行执行。

进入 SOLO 模式后,整个工作区分成了三栏,最左侧多出了一个任务栏(上图的红框)。

你可以在任务栏里面,点击"+"号,新建 Subagent 子任务(下图)。

上图中,新建子任务时,可以选择内置的智能体,也可以新建智能体,由不同的智能体负责执行子任务。

多个子任务可以并行执行。你在任务栏随时切换,查看每个任务执行到哪一步了。

上图就是同时新建了三个子任务,每个任务都有中文标题,可以很清晰了解它们的用途。

这个并行执行的任务栏,除了 TRAE 的 SOLO 模式,我在其他国产 AI 编程工具里面就没见过,希望能够跟进。

五、

SOLO 模型还提供其他一些 IDE 模式没有的功能。

(1)Plan 功能:先对任务进行思考,产生一个"执行计划",等你批准以后再实际执行(下图)。

(2)上下文压缩:智能压缩过长的上下文,防止上下文变得太长导致的模型效果下降,同时显著节省使用 AI 的成本。

(3)代码变更:更好的代码 DiffView 视图,帮助用户快速了解 AI 对代码的变更。

六、

最后总结一下,TRAE 的 SOLO 模式提供了很多 IDE 模式下没有的功能,更接近终端的用法。

由于贴近终端,所以它能做到多任务并行,以及任务执行过程中更好的实时感知。

TRAE 在一个软件里面,集成了 IDE 和 SOLO 两种模式,无疑为程序员提供了最大的灵活性。

再加上国内版完全免费,超大上下文窗口,对于那些既想拥有 IDE 的便捷性,又想拥有终端多任务并行能力的同学,可谓再合适不过的选择。

TRAE 国内版和国际版,都有 SOLO 模式,区别是国内版免费,而国际版提供国外模型,大家可以根据需求选择下载。

(完)

文档信息

  • 版权声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证
  • 发表日期: 2025年11月26日

VS Code 使用国产大模型 MiniMax M2 教程

一、

上周,我写了一篇 Claude Code 接入国产大模型的教程,就有同学问我,为什么不用 VS Code?

问得好。我习惯命令行了,确实忽略了 VS Code。

今天就补上,我来介绍,如何不用插件在 VS Code 里面使用 Claude Code。

我真心觉得,Claude Code 比插件好用,所以试试看跳过插件,直接在 VS Code 里面使用它。

跟以前一样,这一次 Claude Code 也是接入国产大模型,我选的是 MiniMax M2。它的质量很不错,而且这周有活动。

二、

这次评测的题目很有趣,我自己都很喜欢。

它是一个老外程序员最近想出来的,已经在国外引起了轰动。

他用了九个著名模型,生成网页时钟的动画,然后把这些动画放在网站上,网站标题就叫"AI 时钟"。

说来奇怪,这个测试看上去不难,但是大多数模型生成的效果并不好,有些甚至很差。

举例来说,下图是 OpenAI 公司 GPT-5 模型生成的时钟,让人无语。

这个时钟的提示词如下,大家可以拿来自己测。

Create HTML/CSS of an analog clock showing ${time}. Include numbers (or numerals) if you wish, and have a CSS animated second hand. Make it responsive and use a white background. Return ONLY the HTML/CSS code with no markdown formatting.

翻译成中文就是:

"创建一个显示时间 ${time} 的模拟时钟的 HTML/CSS 代码。如果需要,可以包含数字,并添加 CSS 动画秒针。使其具有响应式设计,并使用白色背景。仅返回 HTML/CSS 代码,不要包含任何 Markdown 格式。"

我也拿它来测试,看看 MiniMax M2 的效果如何。

三、

进入正题之前,我想强调一下,VS Code 与 Claude Code 是两种截然不同的工具。

VS Code 是 IDE,你是在 IDE 里面使用 AI。

Claude Code 是命令行工具,你是在终端窗口使用 AI。

它们的特点完全不同。IDE 支持智能感知(intellisense)和自动补全,而命令行支持调用系统工具和脚本,还能自动化集成,以及并行执行。

所以,它们两个不是替代关系,而是互补关系。你应该根据需要,选择最合适的工具。

我要演示的方法,正是将 IDE 和命令行结合起来,让你具有最大的灵活性。

四、

我用来测试的模型是 MiniMax M2,说一下为什么选择它。

它是上月底(10月27日)发布的,很多评测显示它是编程能力最强的开源模型之一,而且在 OpenRouter 平台上,它是 Token 调用量最大的国产模型。

我当时对它做了评测,大家还有印象吗?结论是,它的编程表现超出了我的预期。

但是那个时候,它没有包月套餐,只能按 API 使用量计费,就让人不敢多用。

现在不一样了,上个周末,它突然推出了 Coding Plan 包月套餐,有三档资费。

最低一档针对普通强度的使用,首月只要9.9元,(续费29元/月),这就很划算了。

除了这个优惠活动,它还有两个特点,很适合这篇教程。

(1)兼容性好,接入外部工具很容易。我用它接入 Claude Code 和 VS Code 都非常顺利。

官网文档给出接口示例的工具非常全,包括 Cursor、Cline、Codex、Kilo Code、Droid、Trae、Grok、OpenCode、iFlow 等等。

(2)响应速度、生成速度快。它的 API 服务器,在国内的响应时间一般是几十毫秒,每秒生成 Token 的数量(即 TPS 指标)超过100,比国外模型快得多。

五、

现在进入正题,首先是一些准备工作,要将 MiniMax M2 接入 Claude Code。

具体步骤就不详述了,大家按照前一篇教程就可以了。

简单说,就是新建一个claude-minimax 脚本(下图),将从 MiniMax M2 官网获取的接口参数填入。

完成后,可以测试一下,看看能否正常运行。


$ claude-minimax --version

六、

下面就是在 VS Code 使用 Claude Code 生成网页时钟的测试。

第一步,新建一个本地目录作为项目目录,比如ai-clock


$ mkdir ai-clock 

然后,在 VS Code 里面打开这个目录 ai-clock,作为工作区。

第二步,打开 VS Code 的菜单"终端/新建终端",在这个终端窗口里面,输入 claude-minimax


$ claude-minimax

这时,窗口会提示你授予权限,同意后,就会进入主界面,大概就是下面这样。

现在,我们就能在 VS Code 里面使用命令行的 Claude Code 了。

这时,你既可以使用 IDE 编写代码,又可以通过命令行使用 AI 模型,兼得两者的优势。

第三步,在 Claude Code 的提示符后面,输入/init命令,用来在仓库里面生成一个 CLAUDE.md 文件,记录 AI 对这个仓库操作。


/init

生成结束后,你可以打开看一下 CLAUDE.md 文件(下图)。

因为我们这个示例仓库是空的,所以文件里面没什么内容。如果是有现成代码的仓库,文件里面会有 AI 对代码库的详细解析。

这个文件的作用是当作上下文,每次查询模型时,都会自动附上这个文件,以便模型了解代码库。

如果在提示框输入反斜杠,Claude Code 就会显示所有可用的命令(下图)。

通过这些命令,我们就能使用 Claude Code 的强大功能,完成各种 AI 操作了。

这一步是 Claude Code 的基础用法,对所有项目都是通用的。

第四步,在提示框输入前面的提示词(下图),让模型生成网页时钟。

MiniMax M2 思考了不到一分钟,就生成完毕了(下图),并且自动把这些代码写入文件 index.html

打开网页就是下面的效果。

真的很不错,第一次就能有这样的效果。钟面的形状正确,秒钟跳动的动画十分流畅,每秒都在刷新,显示当前时间。

大家可以使用这个提示词,自己去生成看看,如果手边没有 Claude Code,可以在官网上执行。

也可以查看我得到的完整代码,复制保存成 HTML 文件,在浏览器打开。

七、

从这个测试结果来看,MiniMax M2 的生成结果,无论是横向对比,还是实际效果,都是令人满意的。

结合它现在的价格,性价比很高,我认为值得推荐给大家上手尝试。

最后,转发一下他们的 Coding Plan 活动的海报,首月9.9元,一杯咖啡的钱,包月使用最新的 AI 编程模型,需要者自取。

(完)

文档信息

  • 版权声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证
  • 发表日期: 2025年11月19日

国产大模型接入 Claude Code 教程:以 Doubao-Seed-Code 为例

一、

国产大模型如火如荼,新模型层出不穷,大家有没有在用?

很多同学用惯了现有模型,懒得尝试新模型,真的很可惜。

我的做法是,只要是新模型,就尽量试用,体验最新训练成果。而且,推广期往往有优惠,不用白不用。

今天就来分享,我怎么把国产大模型接入 Claude Code。

大家知道,Claude Code 是眼下最流行、公认功能最强的 AI 终端,但是限制国人使用。所以,我们要换掉它的底层模型。

大家用我的方法,只需要几分钟,就可以简易快速地接入各种国产大模型,丝滑使用。

这几天,字节旗下的豆包,正好发布了最新的编程模型 Doubao-Seed-Code

我就拿它来演示,顺便测一下这个模型。

二、

我要分享的方法,完全不影响 Claude Code 本身,它还能正常使用。

也就是说,执行 claude 命令,调用的还是原来的 Claude Sonnet 4.5 模型。


$ claude

我会新增一个 claude-doubao 命令,执行后底层模型就切换了。


$ claude-doubao

这时,Claude Code 的功能一样都不少,但是使用的模型已经变成了 Doubao-Seed-Code。

上面两个命令,可以同时使用,互不影响。你还能继续添加其他模型,每一个模型都有自己的调用命令,最大程度方便测试新模型。

三、

开始之前,我先简单介绍一下 Doubao-Seed-Code,优秀的国产模型值得好好宣传。

它属于豆包大模型系列,是该系列第一个专门用于编程推理的模型。也就是说,这是字节跳动首次发布编程模型。

根据 SWE-bench 的评测,它和同是字节旗下的智能 IDE 产品 Trae 的组合,在 SWE-Bench-Verified 的排行榜位列第一。

我对这个模型非常感兴趣,主要有三个原因。

(1)它是大厂的主推模型,模型质量、性能表现、响应速度都有保证。

(2)它原生兼容 Anthropic API,可以丝滑接入 Claude Code,不用任何调整,是国外模型很好的平替。

(3)它价格便宜,现在有一个 Coding Plan 活动,可以 API 包月。一般强度使用的情况下,首月只要9.9元(续费40元/月),官方的宣传是"属于国内最低价格"。

大家可以在火山方舟,开通这个模型的 API Key,后面要用到。

四、

下面就来演示,Doubao-Seed-Code 如何快捷接入 Claude Code。

如果你已经安装了 Claude Code,下面的方法完全不影响,还是正常使用。

如果还没有安装 Claude Code,但想体验它的 Claude Sonnet 4.5 模型,可以根据官方文档进行安装,跟下面的方法也不冲突。

更改底层模型,只需要三个步骤,几分钟即可。

第一步,新建一个项目目录claude-model,在里面安装一个单独的 Claude Code。


$ mkdir ~/claude-model
$ cd ~/claude-model
$ npm init -y
$ npm install @anthropic-ai/claude-code

然后,新建一个子目录 .claude-doubao,用来存放豆包的配置文件和缓存。


$ mkdir .claude-doubao

第二步,新建一个子目录 bin,用来存放可执行脚本。


$ mkdir ~/claude-model/bin

然后,要把这个 bin 目录放入 PATH 变量,让系统可以找到里面的命令。

PATH 变量的设置,macOS 可以修改 ~/.bash_profile 文件,Linux 可以修改 ~/.bashrc 文件,大概改成下面这样。


export PATH="$HOME/claude-model/bin:$PATH"

改完后,别忘了重启终端。

第三步,在上一步创建的 bin 目录里面,新建一个名为claude-doubao 的脚本,用来调用豆包模型。


$ touch ~/claude-model/bin/claude-doubao

在这个 claude-doubao 脚本里面,输入下面的内容。


#!/usr/bin/env bash
# Wrapper for Claude Code CLI using Doubao API

CLAUDE_BIN="$HOME/claude-model/node_modules/.bin/claude"

# Inject API credentials
export ANTHROPIC_AUTH_TOKEN="YOUR_DOUBAO_API_KEY"
export ANTHROPIC_BASE_URL="https://ark.cn-beijing.volces.com/api/compatible"
export ANTHROPIC_MODEL="doubao-seed-code-preview-latest"
export API_TIMEOUT_MS=3000000

# Keep a separate config dir (optional)
export CLAUDE_CONFIG_DIR="$HOME/claude-model/.claude-doubao"

exec "$CLAUDE_BIN" "$@"

注意,上面脚本里面的 API Key,要填入你自己申请的 Key。另外,模型的名称和 URL 可能会发生变化,最好核对一下最新的官方文档。

然后,将它变成可执行脚本。


$ chmod +x ~/claude-model/bin/claude-doubao

这样就完成了所有步骤,可以开始使用了。

先测一下,Claude Code 是否正常运行。


$ claude-doubao --version

以后,调用 Doubao-Seed-Code 模型,就用 claude-doubao 命令;调用原始的 Claude Code,就用 claude命令。


# 调用 Doubao-Seed-Code
$ claude-doubao

# 调用原始模型
$ claude

上面的方法是通用的,其他模型也可以这样添加。

五、

下面,我们就用 Claude Code 来调用 Doubao-Seed-Code 模型,测试它的表现。

以前,有一个著名的游戏《太空侵略者》(Space Invaders),大家都玩过吧,就是战斗机发射子弹,击落外星人舰队。

我让 Doubao-Seed-Code 来生成这个游戏。

首先,新建一个项目目录 space-invaders,在该目录中启动 Claude Code(使用claude-doubao命令)。


$ mkdir space-invaders
$ cd space-invaders
$ claude-doubao

然后,填入提示词,"使用 HTML 和 JavaScript 在网页上实现《太空侵略者》"。

Write an HTML and JavaScript page implementing space invaders

屏幕上就会不停滚动模型的思考步骤,大概两三分钟,所有文件就在 space-invaders 目录里面生成完毕。

上面就是浏览器的网页截屏,我没有做任何的修改,第一次生成就是可玩的,没有报错,所有操作都正常,令人满意。

生成的 HTML 源码看这里,你可以复制过去,在浏览器打开玩玩看。模型的完整对话看这里

接着,我还测试让它生成的"鹈鹕骑自行车"的 SVG 图片,大家自己看效果吧。

六、

总结一下,我用下来,Claude Code 接入 Doubao-Seed-Code 以后,用起来非常流畅,响应速度快,体验上跟原生模型没有差异。

至于 Doubao-Seed-Code 这个编程模型本身,总体上令人满意:一步步的推理非常清晰,思考时间短,生成的代码完成度高,且容易读懂,往往一次就能运行成功。

考虑到它现在有 Coding Plan 活动,9.9元就可以 API 包月,性价比很高,大家如果需要编程模型,建议开通。

(完)

文档信息

  • 版权声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证
  • 发表日期: 2025年11月11日

大模型比拼:MiniMax M2 vs GLM 4.6 vs Claude Sonnet 4.5

一、

上个月,我写了一篇文章,比较了两个大模型。

就有人留言,两个模型太少了,能不能加入其他模型?

正好上周(10月27日),MiniMax 公司发布了 M2 模型,代表了国产大模型的最新水平。

我就想,可以测测它的实战效果,跟智谱公司的 GLM 4.6 和 Anthropic 公司的 Claude Sonnet 4.5 对比一下。

毕竟它们都属于目前最先进的编程大模型,跟我们开发者切身相关。

二、

先要说明,其实我不太熟悉 MiniMax 公司,它比较低调。

我只知道,这家公司专门研发大模型,产品有文本模型、视频模型、音频模型等等,但都不是非常热门。我就没有特别关注。

上周,我在滑推特的时候,看到一些老外在议论(123),这才知道 MiniMax 发布了新的旗舰模型 M2。

上面说话的这个人是 HuggingFace 大模型社区的负责人,提到了 M2 模型在 Artificial Analysis 性能评比之中排名世界第五,开源模型第一。

当天的 HuggingFace 热度榜上,它也是第一名。

OpenRouter 的大模型全球调用量排名,它这周排在第三。

我就来了兴趣,准备好好试用一下。

三、

根据 MiniMax 公司的说明,M2 模型的编程能力特别强,是目前最优秀的编程模型之一。

大家知道,国际上最流行的编程模型现在是 Claude Sonnet 4.5,国内的 GLM 4.6 模型也很强,我就把它们三个放在一起对比。

简单起见,我就直接在官方的网页版(国内版国外版)上运行测试,大家可以跟着一起动手试试看。

网页版实际是官方的智能体产品 MiniMax Agent,底层用的就是 M2 模型。

网页使用是免费的,API 调用现在也是免费期,为期两周。后面定价是百万 tokens 输入/输出 2.1元/8.4元人民币,官方宣传只有 Claude 价格的8%。

它的其他链接,我也列一下,文档仓库在 GitHub,API 调用指南(兼容 OpenAI 和 Anthopic 格式)看官方文档,模型下载在 HuggingFace,下载以后可以本地部署使用(如果条件允许)。

四、

我的测试题来自著名程序员西蒙·威利森(Simon Willison),他的网站有 Cluase Sonnet 4.5 的测试结果

此前,我用这些题目测过智谱公司的 GLM 4.6 模型,大家可以参考

本文主要是 MiniMax M2 的测试表现。

五、

第一题,测试模型理解和运行代码的能力。

拉取代码仓库 https://github.com/simonw/llm ,然后通过下面的命令运行测试用例。

pip install -e '.[test]'
pytest

上面的提示词要求模型抓取一个 Python 仓库,运行里面的测试用例,并返回结果。

从网页的显示来看,Minimax Agent 显然内置了沙盒,会在隔离环境的命令行下运行代码(下图)。

整个运行过程大约三分钟,然后它给出了结果:运行通过了466个测试用例。这个结果完全正确。

令我惊喜的是,除了运行结果,它还给出了覆盖率分析(下图),指出测试用例覆盖了代码的哪些功能。我还没在其他模型见过主动提供覆盖率的。

完整的对话看这里

六、

第二题,测试大家最关心的代码生成能力,看看它能不能按照要求生成应用程序。

我还是使用上面的仓库,要求 M2 为其增加一个功能,不仅需要修改代码,还需要修改数据库结构,并增加配套的测试用例。

1、代码仓库 https://github.com/simonw/llm 是一个 AI 对话应用,它将用户的提示和 AI 的响应存储在 SQLite 数据库中。

2、它目前使用线性集合,保存单个对话和响应。你尝试在响应表中添加一个 parentresponseid 列,并通过该列将对话的响应建模为树状结构。

3、编写新的 pytest 测试用例,验证你的设计。

4、编写一个 tree_notes.md 文件,首先将你的设计写入该文件,然后在运行过程中将该文件用作笔记。

这个任务比较复杂,运行时间稍微长一点。

这里有一个插曲。在运行过程中,它突然提示读取 GitHub 仓库没有成功,这时出现了我意外不到的一幕。

它竟自动切换到第三方的 deepwiki.com 去获取仓库。后面,分析数据库结构时,它又切换到 datasette.io 去分析 SQLite 数据库。这种第三方云服务的自动切换,我也是第一次见,可惜没来得及截图。

任务完成后,它给出了一段总结(下图),详细描述了它做了哪些事情,包括修改数据库、新增测试用例等等。

它甚至增加了一个示例文件(下图),演示新增的功能怎么用,还有一个示例图,演示修改后的对话结构,提示词里面可没要求它这么做。

完整的对话看这里

另外,官网的画廊有很多它生成的应用,我觉得也值得看一下。

七、

第三题就是西蒙·威利森发明的"鹈鹕骑自行车"场景,测试它的理解和推理能力。

生成鹈鹕骑自行车的 SVG 图片。(Generate an SVG of a pelican riding a bicycle)

这是现实中不存在的情景,全靠模型自己推理出来。理解能力越强,生成的图像就越逼真。

下面就是它生成的结果,完整的对话看这里

作为比较,我把另外两个模型的结果也贴出来。

GLM 4.6

Claude Sonnet 4.5

我觉得,MiniMax M2 的结果(第一张图片)有两个值得注意的地方。首先,它添加了道路;其次,它的自行车结构相对更完整,只是缺了握把。另外,要是那只鹈鹕的姿势更像"骑车"就好了。

八、

测试就到这里,至于 GLM 4.6Claude Sonnet 4.5 的结果对比,大家可以看它们各自的链接,自行比较。

我必须诚实地说,MiniMax M2 的表现超出了我的预期

最吸引我的地方,还不是运行结果本身,而是它处理问题的方式,对用户很友好,会添加一些帮助理解的辅助结果,让你觉得很易用(accessible)也很易懂,这也从侧面增强了生成结果的可靠性。

我倾向于相信,各种评测结果确实是 M2 的真实实力。再考虑到它的 API 价格(现在还是免费期),我会在接下来的工作中使用它,也推荐大家试试看。

(完)

文档信息

  • 版权声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证
  • 发表日期: 2025年11月 4日

错误处理:异常好于状态码

错误处理有不同的方式。

JavaScript 和 Python 是抛出异常, Rust 语言是变相抛出异常。

C 语言和 Go 语言则是返回一个错误值,你必须判断该值是否为 -1 或空值。

我一直想知道,哪一种方式更好?

前不久,我读到一篇多年前的文章,明确提出抛出异常好于返回状态码。他的理由很有说服力,文章好像还没有中译,我就翻译出来了。

异常与返回状态码

作者:内德·巴切尔德(Ned Batchelder)

原文网址:nedbatchelder.com

在软件中,错误处理有两种方式:抛出异常(throwing exceptions)和返回状态码(returning status codes)。

几乎所有人都认为异常是更好的处理方式,但有些人仍然更喜欢返回状态码。本文解释为什么异常是更好的选择。

一、代码干净

异常可以让你在大部分代码中省去错误处理步骤。它会自动通过不捕捉异常的层,向上传递。你因此可以编写完全没有错误处理逻辑的代码,这有助于保持代码的简洁易读。

让我们比较一下,编写同一个简单函数的两种方法。

先是返回状态码。


STATUS DoSomething(int a, int b)
{
    STATUS st;
    st = DoThing1(a);
    if (st != SGOOD) return st;
    st = DoThing2(b);
    if (st != SGOOD) return st;
    return SGOOD;
}

上面示例中,必须判断DoThing1(a)DoThing2(b)的返回值是否正常,才能进行下一步。

如果是抛出异常,就不需要中间的错误判断了。


void DoSomething(int a, int b)
{
    DoThing1(a);
    DoThing2(b);
}

这只是最简单的情况,如果遇到复杂的场景,状态码带来的噪音会更严重,异常则可以保持代码的整洁。

二、有意义的返回值

状态码会占用宝贵的返回值,你不得不增加代码,判断返回值是否正确。

有些函数本来只需要返回一个正常值,现在不得不增加返回错误的情况。随着时间的推移,代码量不断增长,函数变得越来越大,返回值也越来越复杂。

比如,很多函数的返回值是有重载的:"如果失败,则返回 NULL",或者失败返回 -1。结果就是每次调用这个方法,都需要检查返回值是否是 NULL 或 -1。如果函数后来增加新的错误返回值,则必须更新所有调用点。

如果是抛出异常,那么函数就总是成功的情况下才返回,所有的错误处理也可以简化放在一个地方。

三、更丰富的错误信息

状态码通常是一个整数,能够传递的信息相当有限。假设错误是找不到文件,那么是哪一个文件呢?状态码无法传递那么多信息。

返回状态码的时候,最好记录一条错误消息,放在专门的错误日志里面,调用者可以从中获取详细信息。

异常完全不同,它是类的实例,因此可以携带大量信息。由于异常可以被子类化,不同的异常可以携带不同的数据,从而形成非常丰富的错误消息体系。

四、可以处理隐式代码

某些函数无法返回状态码。例如,构造函数就没有显式的返回值,因此无法返回状态码。还有一些函数(比如析构函数)甚至无法直接调用,更不用说返回值了。

这些没有返回值的函数,如果不使用异常处理,你不得不想出其他方法来给出错误信息,或者假装这些函数不会失败。简单的函数或许可以做到无故障,但代码量会不断增长,失败的可能性也随之增加。如果没有办法表达失败,系统只会变得更加容易出错,也更加难以捉摸。

五、错误的可见性

考虑一下,如果程序员疏忽了,没有写错误处理代码,会发生什么情况?

如果返回的状态码没有经过检查,错误就不会被发现,代码将继续执行,就像操作成功一样。代码稍后可能会失败,但这可能是许多步操作之后的事情,你如何将问题追溯到最初错误发生的地方?

相反的,如果异常未被立刻捕获,它就会在调用栈中向上传递,要么到达更高的 catch 块,要么到达顶层,交给操作系统处理,操作系统通常会把错误呈现给用户。这对程序是不好的,但错误至少是可见的。你会看到异常,能够判断出它抛出的位置,以及它应该被捕获的位置,从而修复代码。

这里不讨论错误未能报出的情况,这种情况无论是返回状态码还是抛出异常,都没用。

所以,对于报出的错误没有被处理,可以归结为两种情况:一种是返回的状态码会隐藏问题,另一种是抛出异常会导致错误可见。你会选择哪一种?

六、反驳

著名程序员 Joel Spolsky 认为,返回状态码更好,因为他认为异常是一种糟糕得多的 goto 语句。

"异常在源代码中是不可见的。阅读代码块时,无法知道哪些异常可能被抛出,以及从哪里抛出。这意味着即使仔细检查代码,也无法发现潜在的错误。"

"异常为一个函数创建了太多可能的出口。要编写正确的代码,你必须考虑每一条可能的代码路径。每次调用一个可能抛出异常的函数,但没有立即捕获异常时,函数可能突然终止,或者出现其他你没有想到的代码路径。"

这些话听起来似乎很有道理,但如果改为返回状态码,你就必须显式地检查函数每一个可能的返回点。所以,你是用显式的复杂性换取了隐式的复杂性。这也有缺点,显式的复杂性会让你只见树木不见森林,代码会因此变得杂乱无章。

当面临这种显式复杂性时,程序员会写得不胜其烦,最后要么用自定义的方法隐藏错误处理,要么索性省略错误处理。

前者隐藏错误处理,只会将显式处理重新变为隐式处理,并且不如原始的 Try 方法方便和功能齐全。后者省略错误处理更糟糕,程序员假设某种错误不会发生,从而埋下风险。

七、总结

返回状态码很难用,有些地方根本无法使用。它会劫持返回值。程序员很容易不去写错误处理代码,从而在系统中造成无声的故障。

异常优于状态码。只要你的编程语言提供了异常处理工具,请使用它们。

(完)

文档信息

  • 版权声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证
  • 发表日期: 2025年10月22日