Friction as Design Signal(摩擦作为设计信号)
定义
Friction as Design Signal 是一种工程判断:开发中的困难、停顿和理解阻力不一定是浪费,它们可能是在提示架构、抽象、数据模型或团队协作方式有问题。
为什么 AI 时代更重要
Vibe Coding 的吸引力在于消除摩擦:更快生成代码、更快看到产品、更少手动查资料。Harris 的反向提醒是,摩擦本身常常携带信息。
当开发者逐行阅读陌生代码、写 ADR、暂停实现、出门散步、重新审视架构时,他们不是低效,而是在让系统的真实约束浮上来。LLM 可以帮助执行,但如果它直接把所有阻力都“编码穿过去”,团队可能错过更早的设计信号,最后留下只有 prompt 历史、没有设计理由的系统。
Why I Don’t Vibe Code 的重点不是反对 LLM,而是反对把设计判断、抽象选择和责任承担交给 LLM。摩擦作为设计信号,就是这条边界的操作化版本:AI 可以帮你跨过偶然复杂性,但不能替你判断哪些阻力正在暴露 本质复杂性。
摩擦分类
不是所有摩擦都值得保留。治理这个概念时,先要区分摩擦类型。
| 摩擦类型 | 例子 | 处理方式 |
|---|---|---|
| 偶然摩擦 | API 参数难查、格式转换、样板代码、环境命令 | 交给工具或 Agent 自动化 |
| 本质摩擦 | 概念边界不清、行为难测试、领域例外变多 | 暂停、建模、补测试和 ADR |
| 社会摩擦 | 责任归属、团队协作、用户后果、合规风险 | 明确 owner、升级路径和验收标准 |
| 认知摩擦 | 读不懂历史代码、命名混乱、抽象过早 | close reading,重命名,清理概念模型 |
好的 Agentic Engineering 不是消灭全部摩擦,而是把不同摩擦放进不同处理路径。
何时保留摩擦
出现以下信号时,摩擦通常值得被认真读取。
- 代码“能写出来”,但测试难写,因为行为边界没有说清。
- 类名、函数名和领域词反复换,说明概念模型不稳定。
- Agent 连续生成多个可运行方案,但每个方案都让系统更难理解。
- 开发者必须解释一串历史例外,才能说明一个小需求。
- 需求牵涉真实人的损失、公共服务失败、合规或法律后果。
- 团队想跳过 ADR、review 或用户验证,只因为 AI 已经生成了代码。
这些摩擦不是速度问题,而是系统在提示:当前抽象、边界或责任模型不够好。
何时消除摩擦
以下摩擦通常应被工具消除,而不是被浪漫化。
- 机械查文档、找参数、转换格式、补样板代码。
- 低风险、可回滚、可自动验证的小改动。
- 明确重复的命名清理、文件拆分和测试补齐。
- 环境配置和工具链噪音,只要不会掩盖真实设计问题。
这里可以放心使用 Agent。技术债务避免 的核心就是让 coding agent 处理概念简单但人工耗时的清债任务,同时保留测试、review 和责任边界。
操作流程
把摩擦当作设计信号时,可以按五步处理。
停下
-> 命名摩擦
-> 分类:偶然 / 本质 / 社会 / 认知
-> 决定:自动化 / 记录 / 重构 / 升级
-> 用测试、ADR 或代码变更固化学习这个流程的关键是留下可复用证据。只是在脑中“感觉哪里不对”不够;要把判断写成测试、ADR、命名、边界、约束或删除代码的决定。
与 Vibe Coding 的边界
Vibe Coding 的风险不是“用了 AI”,而是把速度和流畅感误认为理解。LLM 可以把难写的代码快速写完,但如果开发者不知道为什么这段代码难写,就可能把结构性警报包进更多生成代码里。
因此,摩擦作为设计信号要求人类保留三项工作:
- Close reading:读懂系统为什么已经长成这样。
- Design record:用 ADR、测试和注释记录关键选择。
- Accountability:承认最终后果仍由团队承担,而不是由模型承担。
这也连接 YAGNI 和 AI-Restraint:有些时刻正确动作不是继续生成,而是少做、删除、推迟或请人审。
注意力和承诺层面的摩擦
20260531-thoughts-hmmz 把“摩擦作为信号”从代码设计扩展到个人注意力和产品承诺。作者的问题不是 AI 不能生成软件,而是它太容易把一个“快速脚本”扩张成无人维护、无真实需求、无市场路径的项目。
这说明有些摩擦不只是在提示架构问题,也在测试人的承诺:
- 我真的需要这个东西吗?
- 我愿意维护它吗?
- 它解决的是原始问题,还是只是生成过程给了我即时奖励?
- 如果没有 AI 的流畅反馈,我还会做它吗?
这类摩擦被完全消除后,就会进入 零摩擦范围蔓延:每个新增动作都局部合理,但整体注意力和维护责任被拖向低价值方向。
关键数据点
- 作者把 close reading 视为理解代码选择、语言惯用法和约束来源的必要过程。
- 当写代码变难时,作者把它当作当前架构路径可能错误的信号,而不是单纯的生产力问题。
- 作者用 ADR 固化当下假设、设计理由和后果,以便未来团队能重建“当时为什么这么做”。
- source summary 明确提醒:并非所有摩擦都值得保留,环境配置、API 参数和样板代码常常只是浪费认知带宽。
- 迁移判断:AI Coding 的正确目标不是消灭开发者思考,而是把人的判断力放在更高杠杆位置。
前提与局限性
- 前提: 摩擦来自真实复杂性,而不是文档缺失、工具损坏或重复劳动。
- 前提: 团队愿意把停顿视为理解系统的机会,而不是只用速度衡量工程价值。
- 局限: 低价值摩擦仍应被工具消除,例如机械查参数、重复格式转换、可完全自动验证的小改动。
- 局限: 摩擦不能被浪漫化;没有验证、没有记录、没有设计产出的停顿也可能只是拖延。
- 局限: 资深工程师更容易从摩擦中读出设计信号;新手可能需要 LLM 和导师先帮助跨过入门门槛。
- 误用风险: 把“保留摩擦”当成拒绝工具、拒绝自动化或拖慢团队的借口。
关联概念
- Essential-Complexity — 摩擦经常是本质复杂性显形的方式。
- Ownership — 愿意面对摩擦,是对系统后果负责的一部分。
- Judgment — 判断哪些摩擦该消除、哪些摩擦该保留。
- Agentic-Engineering — 好的 Agentic Engineering 应保留关键设计反馈,而不是只追求生成速度。
- Technical-Debt-Avoidance — 提前识别摩擦可避免把结构问题沉淀为技术债。
- Vibe-Coding — 如果只追求流畅生成,容易绕过设计信号。
- YAGNI — 少做和推迟实现是保留判断空间的一种方式。
- AI-Restraint — 高风险和不确定场景中,停止行动本身是能力。
- Code-as-Conceptual-Infrastructure — 摩擦常常暴露代码背后的概念模型问题。
- Zero-Friction-Scope-Creep — 当筛选摩擦被 AI 消除,项目和功能会无边界扩张。