📐 回归手写代码:一位开发者的7个月“氛围编程”反思

原文标题:I'm going back to writing code by hand · 发布时间:2026-05-09 · 作者:k10s 开发者
⚡ 核心结论:AI 擅长构建功能,而非架构。纯粹的“氛围编程”(vibe-coding)会导致项目在复杂性压力下崩溃,人类必须始终在核心环路中负责架构设计、范围控制和状态管理。

一、 项目崩溃的根源:“上帝对象”的诞生

通过234次提交、约30个周末的GPU集群仪表盘项目,作者发现AI倾向于将所有UI组件、客户端、视图状态塞进一个巨大的Model结构体:

  • 一个 1690 行model.go,包含UI部件、K8s客户端、日志状态、导航历史等无关字段。
  • 500 行Update() 函数,内含 110 个 switch/case 分支,使用字符串比较 (m.currentGVR.Resource ==) 区分不同视图行为。
  • 需要 9 处手动 nil 赋值 来清理跨视图的“幽灵数据”,一旦遗漏就产生渲染错误。

二、 五个核心教训与对策(基于 wreckage)

1. AI 构建功能,而非架构

问题:每次功能都在真空中实现,无视现有其他功能共享的状态。新视图的逻辑被硬编码插入通用资源加载路径。

对策:人类预先写好架构(接口、消息类型、所有权规则),并写入 CLAUDE.md。例如:“每个视图实现 View trait,视图间禁止访问对方状态;添加新视图不得修改现有视图”

2. 上帝对象是 AI 的默认产物

问题:AI 将所有状态集中,导致按键噩梦——同一 s 键在日志视图是“滚动”,在 Pods 视图是“进入 Shell”。键绑定扁平放在一个结构体中。

对策:在 CLAUDE.md 中强制状态所有权规则:每个视图拥有自己的状态和按键映射,应用只负责分发;添加视图即添加文件,而非修改现有文件。

3. 速度幻觉无限扩大范围

问题:AI 让添加功能显得“免费”,项目从“GPU集群专用工具”膨胀为通用 Kubernetes TUI,技术债务暗中累加。

对策:明确写下“不为谁服务”,在指令中限定范围。例如:“仅支持 fleet、node-detail、workload 视图;不添加通用资源视图(pods, services);拒绝非GPU训练场景的功能。”

4. 位置数据是定时炸弹

问题:AI 将结构化数据扁平化为 []string,排序依赖魔法索引(如 row[3] 代表Alloc列)。增删列静默破坏所有逻辑。

对策:强制类型化数据——数据以结构化体(如 FleetNode)流动直到渲染前;列身份由字段名而非索引决定;排序基于命名域。

5. AI 不管理状态转移(并发安全)

问题:AI 生成在闭包中直接修改 UI 状态的代码(如 goroutine 中调用 m.updateTableData()),导致数据竞争(1% 情况显示损坏)。

对策:所有可变状态更新必须发生在主循环中。后台任务通过通道发送类型化消息,主循环接收后原子应用状态;render() 必须是纯函数。

三、 作者的新方向与最终建议

语言切换:从 Go 转向 Rust —— 不是因为 Rust 更优,而是作者对 Rust 有足够直觉来“闻出”代码的坏味道,这种直觉是 AI 无法替代的。
过程改变:在写任何代码之前,亲手完成设计工作(接口、消息类型、所有权规则),将架构决策书面固定后才让 AI 参与编码。
最终结论“你可以放心地回归手写了”(2026-05-10)。AI 在需要长期可维护性、并发正确性和清晰架构的严肃项目中,必须有人类主导。氛围编程适合原型或一次性脚本,但不适合演化的系统。

※ 原文脚注提到 Bubble Tea 框架本身的优秀,架构问题属于开发者;类型安全设计引用 Elm/Rust “使不可能状态不可表达”理念。

💬 Hacker News 热议:AI 生成代码是解放还是陷阱?

讨论源自原博文 · 核心焦点:何时、如何、以及由谁负责任地使用 AI
🧠 总体共识:AI 编程的“魔法”只在边界清晰、反馈迅速、人类紧握方向盘的场景下生效。开发者必须对最终质量负全责。

一、 核心争议阵营:悲观派 vs 乐观派

观点派别核心论据典型代表/实例
悲观派
(AI无法长期维护)
1. 判断力缺陷:AI不会在架构不变式被违反时主动“喊停”,只会写出扭曲代码强行遵守旧约束。
2. 隐患隐蔽:AI擅长“埋雷”,错误灾难性且难以发现,必须逐行审计。
3. 认知债务:理解修正AI代码的精力经常超过手写。
评论者 toss1, kristianp, nostrademons
乐观派
(方法得当则极其高效)
1. 生产力飞跃:正确流程下(计划模式、小模块),10个月做到35万美金ARR。
2. 特定场景优秀:处理重复样板代码、成熟代码库、生成初版方案供筛选时效率极高。
3. 工具而非替身:AI是“超级结对程序员”,需要经验丰富开发者驾驭。
SaaS创始人 Trasmatta, prisen, klabbamm

二、 为什么“先定义架构让AI填充”也会失败?

  • 不变式会过时:需求变化后,原有架构约束可能不合理。AI不会主动质疑,反而写出极端扭曲的代码来“遵守”过时规则。
  • 审查陷阱:AI生成的代码局部可能“正确”,但整体充满违背直觉的变通方案。对AI输出的审查需要比审查人写代码更仔细,否则漏掉隐患。
  • 认知负担转移:开发者从“编写者”变为永久的警惕审查者,总工作量可能不降反增。

三、 成功者分享的严格实践方法

实践策略具体做法目的
强制小粒度每次只让AI工作在几百行代码的模块内,定义清晰的接口(如.h文件);文件数量增加不是问题。限制AI“爆炸半径”,让违规难以隐藏。
计划先行始终使用“计划模式”,先与AI确定实施方案,批准后再生成代码。在抽象层面发现逻辑问题,避免直接生成垃圾代码。
分阶段审查+测试要求AI给出3个方案;逐行审查差异;最后单独生成单元测试验证实现。通过“筛选”而非“修正”获得高质量代码,用测试反向约束。
明确“不为谁服务”在指令中显式写出范围边界,例如“不要添加通用资源视图”。对抗AI特征膨胀,控制复杂度。
工具化约束使用PreToolUse钩子等硬性阻止危险操作(如删除文件、任意shell)。防范AI为达成目标采取的“创造性破坏”。

四、 深层反思:谁负责?价值何在?

责任归属:AI只是工具,人类开发者对最终代码质量负全责。指责AI就像画家指责画笔。
理解的价值:如果你无法独立手写出某段代码,就不该盲目信任AI生成的版本。不理解的部分必须投入时间完全搞懂,否则债务指数级增长。
两种开发者:认为“写代码”很难的开发者极度热爱AI;认为“设计抽象、保证可维护性”才是核心困难的人将AI视作有用工具,但不是革命性突破。
PM类比:AI对项目管理的影响类似——能快速整理工单与知识,但最终战略判断仍属人类核心价值。

📌 推荐做法 vs 绝对禁区
✅ 用AI处理明确的、低风险的、独立的任务(单元测试、CRUD样板、技术探索);在成熟代码库中模仿既有模式;始终“计划-生成-审查-测试”循环。
❌ 让AI自主决定架构或核心不变式;在不理解逻辑的情况下合并大段代码;在无法深度审查的压力环境下依赖AI输出关键模块。

来自资深开发者(C++/硬件)的经验补充

一位近40年经验的评论者指出:文件级粒度是关键——通过严格模块化、公私接口分离,让AI每次只接触几百行代码,配合测试与硬件验证,可以有效避免垃圾代码。但遇到棘手的硬件问题或复杂调试时,AI会“发疯”,需要人类精准地限制其“理解问题”的冲动,仅让它执行探测操作。另一位强调:始终把AI当作“实习生”,而不是架构师。

此外,部分评论者提出“认知债务”概念:如果你不彻底理解AI生成的代码,缺乏理解会指数级增加未来修复成本,最终可能需要完全重写。


总结 AI编程并非乌托邦也非魔鬼,它极大地加速了已知边界内、低模糊性的任务,但无法替代人类对架构演化、不变式判断和长期可维护性的深度责任。成功的案例都依赖于经验丰富者的严密流程、硬性约束与高强度审查。

※ 以上提炼自原HN讨论串中数十条高赞评论,涵盖toss1, Trasmatta, nostrademons, CaliLuke, chicagodave 等多位一线开发者的观点碰撞与实践记录。