Vibe Coding 用久了,代码手感真的会退化——以及我怎么试图解决这个问题

Vibe Coding 用久了,代码手感真的会退化------以及我怎么试图解决这个问题

正文

最近有一个感受越来越强烈:Vibe Coding 用久了,手感在退化

不是不会写了,而是不够顺了。useMemo 的依赖数组位置要想一秒,SQL Join 的 ON 子句要停顿,reduce 的初始值要回忆一下写在哪。这些以前不用想的东西,现在需要"想"了。

我相信不止我一个人有这种感觉,但很少有人认真聊过这个现象。


手感退化到底是怎么回事

先说一个认知科学里的概念:自动化处理(automaticity)

当你在键盘上敲 console.log() 的时候,你不会去想"先按 c,再按 o,再按 n......"------你的手指自动完成了整个序列。这就是自动化处理:经过大量重复后,大脑把某个技能下放给无意识处理,不再占用工作记忆的容量。

好处很明显:工作记忆被释放出来,你可以把注意力放在逻辑层面,而不是输入层面。

但有个前提:这个"下放"不是永久的。

长期不用的自动化技能会"降级"。你仍然"知道"怎么做,但从自动变成了需要有意识地去调取------速度变慢、容易卡顿、需要额外思考。

Vibe Coding 时代的典型场景就是:大量代码由 AI 生成,你主要负责审查和调整。这意味着你读代码和改代码的时间增加了,但从零手写代码的时间减少了。手写频率一旦下降,输入层面的自动化就会退化。

结果就是:你理解代码的能力没有变弱,但你把理解转化为输入的速度变慢了。


代码输入和普通打字的区别

有人可能会想:打字速度退化了,去 MonkeyType 刷一刷不就好了?

不完全对。普通打字练习训练的是英文单词和常见句式的流畅度,但程序员每天真正输入的东西和英文文章差别很大:

1. 符号密度高

一段 JavaScript 业务代码里,括号、点号、逗号、分号、等号的比例远高于英文文章。这些符号在普通打字练习中出现频率低,但编程时它们才是卡手的地方。

2. 结构化模板多

const [x, setX] = useState(defaultValue) 这种模式,你不会一个字母一个字母地想------你脑子里是整个模板,手要能一口气敲出来。普通打字练不出这种模板级输入。

3. 缩进和格式是输入的一部分

Python 的缩进、JSX 的嵌套、SQL 的对齐------这些不只是"格式",它们是代码结构的一部分。普通打字不关心缩进层级。

所以,如果要做手感训练,需要一个专门针对代码输入模式的练习工具,而不是通用打字练习。


我的实践:用 Tauri + CodeMirror 做了一个代码手感训练器

为了解决自己的手感退化问题,我花了几周时间做了一个桌面工具:CodeStep

核心思路很简单:把高频代码模式拆成 30 秒到 3 分钟的短片段,让你反复输入,同时给出 WPM、准确率、Combo 连击等实时反馈,帮助重建输入层面的自动化。

下面重点聊技术实现和踩过的坑。


整体架构

复制代码
┌─────────────────────────────────┐
│         Tauri v2 Shell          │
│  ┌───────────────────────────┐  │
│  │     React 18 + TS 前端     │  │
│  │  ┌─────┐  ┌────────────┐  │  │
│  │  │Zustand│ │CodeMirror 6│  │  │
│  │  │Store  │ │  Editor    │  │  │
│  │  └─────┘  └────────────┘  │  │
│  │        Tailwind CSS        │  │
│  └───────────────────────────┘  │
│           Vite 构建             │
│  ┌───────────────────────────┐  │
│  │     Rust 后端(Tauri)     │  │
│  │   - 代码执行沙箱           │  │
│  │   - 本地数据存储            │  │
│  │   - 分享图片生成            │  │
│  └───────────────────────────┘  │
└─────────────────────────────────┘

为什么选 Tauri v2

选桌面框架时比较了 Electron 和 Tauri:

维度 Electron Tauri v2
安装包大小 100MB+ 5-15MB
冷启动速度 2-5s <1s
内存占用 200MB+ 30-60MB
前端技术 不限 不限
后端语言 Node.js Rust

对于"上班前练 3 分钟"这种场景,启动速度和安装体积直接影响使用频率。如果打开就要等 3 秒,很多人就不愿意打开了。Tauri 在这点上有明显优势。

Tauri v2 相比 v1 增加了移动端支持、更完善的插件系统和更好的权限模型,不过目前 CodeStep 只用了桌面端能力。

为什么用 CodeMirror 6 做输入区

这是整个项目最核心的技术选型。

CodeStep 练的是代码,不是普通文本。输入体验要做到:

  • 逐字符验证:每输入一个字符,立即判断对错并高亮
  • 精确的光标和退格控制:退格行为需要自定义逻辑
  • 代码高亮:不同语言需要语法着色
  • 后续扩展:可能要支持 Vim 模式、多语言高亮、输入模式切换

<textarea>contenteditable 都做不到逐字符的精细控制。CodeMirror 6 的 ViewPluginDecoration API 可以精确控制每个字符的样式,EditorView.domEventHandlers 可以拦截每个键盘事件。

核心验证逻辑的简化实现:

typescript 复制代码
// 简化版:逐字符输入验证
function handleInput(view: EditorView, targetCode: string) {
  const pos = view.state.selection.main.head
  const inputChar = view.state.doc.sliceString(pos - 1, pos)
  const expectedChar = targetCode[pos - 1]

  if (inputChar === expectedChar) {
    // 正确:绿色高亮
    addDecoration(pos - 1, pos, 'correct')
    combo++
  } else {
    // 错误:红色高亮,累计错误
    addDecoration(pos - 1, pos, 'error')
    errorCount++
    combo = 0
  }
}

实际实现比这个复杂得多------要处理退格逻辑、组合输入(中文输入法)、Tab 缩进、自动括号配对等边界情况。


踩过的三个坑

坑 1:退格后错误次数要不要减少

最早的设计:退格删掉错误字符,错误次数 -1。

表面看合理------"我已经改回来了嘛"。但练了几轮之后发现:这会让 Accuracy 接近 100%,因为只要退格够快,错误就会被抹掉。训练失去了区分度。

最终的方案:退格恢复到上一字符位置,但错误次数不减少。

这样 Accuracy 反映的是"手误了多少次",而不是"修改后的结果"。更接近真实场景------在业务代码里,你打错了退格改回来,虽然最终代码是对的,但你确实卡了一下。

坑 2:Combo 的反馈不够"爽"

第一版 Combo 只是数字递增,没有额外的视觉和听觉反馈。练了几次发现:Combo 到 50 和 Combo 到 10 的体感差别不大,缺少"触发感"。

后来做了两个改动:

听觉:Combo 超过阈值时,按键音的音调随 Combo 数逐渐升高。到 50 Combo 时声音明显比 10 Combo 时"亮"。

视觉:Combo 突破里程碑(10/25/50/100)时,输入区域边缘出现粒子动画 + 轻微屏幕震动。

typescript 复制代码
// Combo 里程碑反馈
const COMBO_MILESTONES = [10, 25, 50, 100]

function onComboChange(combo: number) {
  // 音调随 Combo 升高
  const baseFreq = 440
  const freq = baseFreq + Math.min(combo, 100) * 3
  playKeySound(freq)

  // 里程碑触发视觉反馈
  if (COMBO_MILESTONES.includes(combo)) {
    triggerParticleBurst()
    triggerScreenShake(combo >= 50 ? 'strong' : 'light')
  }
}

改完之后训练的正反馈明显变强了。这让我意识到:游戏化不一定要做得复杂,关键是反馈要和用户的操作有清晰的因果关联。

坑 3:训练内容的"高频"标准

最开始的训练内容是按"这个语法点重要"来选的,比如 Promise.allSettledProxy handler、WeakMap

用户反馈:这些我平时不写。

后来换了一个标准:真实业务代码里高频出现,而不是语言特性文档里常见的写法

比如 Promise.allSettled 在 MDN 文档里很常见,但在业务代码里出现频率远低于 Promise.all。而 array.filter().map() 这种链式调用,文档里不怎么单独提,但几乎每天都要写。

两者的区别:前者是"值得了解的知识点",后者是"值得练成肌肉记忆的输入模式"。CodeStep 应该只包含后者。


代码执行沙箱的设计

CodeStep 除了 typing(纯输入训练),还有 coding 模式------用户需要写代码并运行,看输出是否正确。

这涉及到在本地安全执行用户代码。当前方案是在 Tauri 的 Rust 层实现:

rust 复制代码
// 简化版:Rust 侧代码执行
fn execute_code(code: &str, language: &str) -> ExecutionResult {
    // 1. 创建临时目录
    let temp_dir = TempDir::new()?;

    // 2. 根据语言写入文件
    let file_path = match language {
        "python" => write_python_file(&temp_dir, code)?,
        "javascript" => write_js_file(&temp_dir, code)?,
        _ => return Err("Unsupported language"),
    };

    // 3. 执行,带超时
    let output = Command::new(get_interpreter(language))
        .arg(&file_path)
        .output()
        .with_timeout(Duration::from_secs(10))?;

    ExecutionResult {
        stdout: String::from_utf8_lossy(&output.stdout).into(),
        stderr: String::from_utf8_lossy(&output.stderr).into(),
        exit_code: output.status.code(),
    }
}

目前已知的问题:

  • 临时目录竞态:多步骤执行时共享同一个临时路径,需要每个执行创建独立目录
  • 超时强制:当前超时只 kill 进程,没有清理子进程的逻辑
  • 沙箱隔离:还未启用 OS 级沙箱,当前仅靠进程隔离

这些都是后续要修的。但作为 MVP,这个方案足够支撑 coding 训练的基本流程。


当前状态和后续计划

CodeStep 目前已经能用,内置了 JavaScript、React Hooks、Python、SQL、Vim、Spring 六个训练包。

后续计划做的方向:

  1. 更多训练包:TypeScript 类型体操、Docker 常用命令、Git 高频操作、正则表达式
  2. 成长数据追踪:WPM / 准确率的长期曲线,薄弱词素分析
  3. 挑战模式:限时闯关,完成后生成分享卡片
  4. 代码执行沙箱加固:独立临时目录 + 进程树超时清理 + OS 沙箱

项目已开源,感兴趣可以搜 CodeStep 看看。想练哪个技术栈也可以告诉我,高频需求会优先安排。


相关推荐
太阳之子1 小时前
开源推荐:一个专为 AI Agent 设计的求职自动化工具
开源
谷哥的小弟1 小时前
(最新版)Git&GitHub实操图文详解教程(02)—安装Git
git·github·安装·配置·下载·图文教程
谷哥的小弟2 小时前
(最新版)Git&GitHub实操图文详解教程(01)—Git的起源
git·github
小此方2 小时前
Re:Linux系统篇(十四)工具篇 · 五:Git 高效协作实战与“三板斧”秘籍
linux·git·github
Pan Zonghui3 小时前
GitHub Bug反馈与修复全流程指南
github·bug
sbjdhjd3 小时前
01| 裸机部署 K8S:从零搭建生产可用集群
运维·经验分享·云原生·kubernetes·开源·kubelet·kubeless
2401_8734794012 小时前
运营活动被薅羊毛怎么防?用IP查询+设备指纹联动封堵漏洞
java·网络·tcp/ip·github
一直会游泳的小猫14 小时前
gstack-guide
开源·安全防护·ai辅助开发·技能工具集·sprint流程
Hical_W15 小时前
Hical 踩坑实录五部曲(五):Boost.MySQL 协程集成的 5 个坑
数据库·mysql·开源