下载 App

【谨慎运用】拒绝AI过度工程手册-第一章【未完】

05/1848 浏览开发心得
         拒绝 AI 过度工程——约束 AI 行为的提示词与沟通策略手册
         Preventing AI Over-Engineering: Constraint Prompts Handbook
                       版本 v4.2 | 2026-05-18
================================================================================
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  前言
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
【一句话定义】
  过度工程 = 代码解决的问题比你实际拥有的问题更多。
【为什么 AI(Claude)特别容易过度工程】
  BUG 是显性破坏:能看见、能定位、能修复。
  过度工程是隐性破坏:代码能跑,看起来"更完善",但在每次未来修改时
  都向你收取复利式的认知成本。
  Claude 的过度工程有三个结构性来源:
  1. 训练数据偏差
     互联网上的代码示例天然展示"完整方案"。Stack Overflow 上被高赞的答案
     通常是通用的、防御性的。Claude 从这些数据学习,默认复现这种风格。
  2. "有帮助"的错误激励
     Claude 被训练为让用户满意。"多给一些"在表面上看起来比"少给一些"
     更负责任。Claude 无法感知你项目的规模和生命周期,
     于是默认按"大型生产系统"的标准设计一个周末项目。
  3. 用复杂度对冲不确定性
     当 Claude 不确定如何干净地实现某个功能时,它会通过增加抽象层来
     "保留退路"。这些抽象不是为你服务的,是为 Claude 自己的不确定性
     服务的。→ 详见第一章 1.13(最重要的 AI 特有模式,含完整分析)
  过度工程的真实成本:
  ┌──────────────────────────────────────────────────────────────────┐
  │  短期:代码量翻倍,审查时间翻倍,理解成本翻倍                  │
  │  中期:需求变化时,多余的抽象层成为修改障碍而非助力            │
  │  长期:项目因复杂度失控被放弃,或维护成本超过重写成本          │
  │  隐性:每次回来看自己的项目时,你需要更长时间"重新进入状态"    │
  └──────────────────────────────────────────────────────────────────┘
【本手册援引的核心原则】
  - YAGNI(You Ain't Gonna Need It)—— Ron Jeffries,XP 方法论
  - KISS(Keep It Simple, Stupid)—— 美国海军设计哲学,1960s
  - Rule of Three —— Martin Fowler《重构》:第三次重复才值得抽象
  - Gall's Law —— 「能运作的复杂系统都从能运作的简单系统演化而来,
                   跳过简单阶段直接设计复杂系统的尝试,从未成功过。」
  - Second System Effect —— Fred Brooks《人月神话》:
                   「工程师在第二个项目中,倾向于把第一个项目里所有
                    "想加但没加"的东西全部塞进去。」
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  第一章:AI 过度工程的 15 种典型模式(含简化前后对比)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  本章识别"是什么"。干预句式见第四章,决策框架见第六章。
────────────────────────────────────────────────────────────────────────────────
1.1 不必要的抽象层
────────────────────────────────────────────────────────────────────────────────
  触发信号:「为了更好的可扩展性…」「为了遵循 SOLID…」「为了便于替换…」
  ❌ Claude 给出(60 行):
    interface EmailSender { send(to, subject, body): Promise<void> }
    class SmtpEmailSender implements EmailSender { ... }
    class EmailSenderFactory { static create(): EmailSender { ... } }
  ✅ 实际需要(8 行):
    async function sendEmail(to, subject, body) {
        await transporter.sendMail({ from, to, subject, text: body })
    }
  判断标准:接口只有一个实现 → 接口是多余的。
  ▶ 干预见第四章 4.1「打断不必要的抽象」
────────────────────────────────────────────────────────────────────────────────
1.2 为"可能的需求"设计(YAGNI 违反)
────────────────────────────────────────────────────────────────────────────────
  触发信号:「考虑到未来可能…」「虽然现在不需要,但…」「为了以后方便…」
  ❌ Claude 给出(Python 场景):
    class StorageBackend(ABC):          # 「以后可能换 S3」
        @abstractmethod
        def save(self, key, data): ...
    class LocalStorageBackend(StorageBackend):
        def save(self, key, data): ...
    class S3StorageBackend(StorageBackend):  # 「备用,还没接入」
        def save(self, key, data): ...
  ✅ 实际需要(你只有本地存储):
    def save_file(path, data):
        Path(path).write_bytes(data)
  Rule of Three:同一逻辑出现第 3 次,且三处会同步修改时,才值得抽象。
  ▶ 干预见第四章 4.1「打断不必要的抽象」
────────────────────────────────────────────────────────────────────────────────
1.3 过度的错误处理
────────────────────────────────────────────────────────────────────────────────
  触发信号:「为了健壮性…」「为了防止极端情况…」「虽然通常不会出错,但…」
  ❌ Claude 给出(内部函数加了公网级别的防御):
    function double(n: number): number {
        if (n === null || n === undefined) throw new Error('n is null')
        if (typeof n !== 'number') throw new TypeError('n must be number')
        if (!isFinite(n)) throw new RangeError('n must be finite')
        if (n > Number.MAX_SAFE_INTEGER / 2) throw new Error('overflow risk')
        return n * 2
    }
  ✅ 实际需要(内部函数,调用方保证类型):
    const double = (n: number) => n * 2
  原则:只在信任边界处校验(用户输入、外部 API 响应)。
  内部函数的调用方已保证合法性时,校验是冗余成本,不是"健壮性"。
  ▶ 干预见第四章 4.1「打断不必要的错误处理」
────────────────────────────────────────────────────────────────────────────────
1.4 过度的配置化
────────────────────────────────────────────────────────────────────────────────
  ❌ Claude 给出(Lua 场景):
    local Config = {
        maxRetries = 3,         -- 你永远不会调整这个
        retryDelay = 1000,      -- 你永远不会调整这个
        timeout = 5000,         -- 你永远不会调整这个
        enableLogging = true,   -- 你永远不会调整这个
    }
    function fetchData(url, options)  -- options 有 12 个可选字段
        options = options or {}
        ...
    end
  ✅ 实际需要:
    function fetchData(url)
        return http.get(url, { timeout = 5000 })
    end
  标准:只有「这个值在不同环境或不同时间真的会变」时才做成配置。
  ▶ 干预见第四章 4.1「打断过度配置化」
────────────────────────────────────────────────────────────────────────────────
1.5 不请自来的重构
────────────────────────────────────────────────────────────────────────────────
  触发信号:「我顺便…」「我还改进了…」「趁这次机会优化了…」
  危险:范围外的每次修改都是新 BUG 的潜在来源,且无法归因。
  ❌ 你要修 line 42 的一个变量,Claude 额外做了:
    · 重命名了 15 个变量("更清晰")
    · 提取了 3 个新函数("更可读")
    · 调整了文件结构("更符合规范")
    · 加了 JSDoc 注释("便于维护")
  ✅ 你要修 line 42,Claude 只改 line 42。
  ▶ 干预见第四章 4.1「打断不请自来的重构」
────────────────────────────────────────────────────────────────────────────────
1.6 过度的注释
────────────────────────────────────────────────────────────────────────────────
  ❌ 噪音注释(增加阅读负担,降低信噪比):
    -- 将 userId 赋值给 userId 变量
    local userId = user.id
    -- 返回 userId
    return userId
  ✅ 有价值的注释(解释"为什么"而非"是什么"):
    -- 用 floor 而非 round:业务要求不足1元不计,避免多收费
    local fee = math.floor(amount * rate)
────────────────────────────────────────────────────────────────────────────────
1.7 引入不必要的依赖
────────────────────────────────────────────────────────────────────────────────
  ❌ 为一行逻辑引入整个库:
    import _ from 'lodash'
    const copy = _.cloneDeep(obj)   // 仅此一处使用 lodash
  ✅ 原生 API 足够时:
    const copy = structuredClone(obj)
  每个额外依赖 = 安全风险 + 升级负担 + 包体积 + 许可证风险。
────────────────────────────────────────────────────────────────────────────────
1.8 类型系统滥用(TypeScript)
────────────────────────────────────────────────────────────────────────────────
  ❌ Claude 给出(为一个只用一次的函数写了 10 行类型体操):
    type UserId = string & { readonly _brand: 'UserId' }
    function createUser<T extends Record<string, unknown>>(
        data: Omit<T, 'id'> & Partial<Pick<T, 'createdAt'>>
    ): T & { id: UserId } { ... }
  ✅ 实际需要:
    function createUser(data: { name: string; email: string }) {
        return { ...data, id: crypto.randomUUID() }
    }
────────────────────────────────────────────────────────────────────────────────
1.9 过度的日志框架
────────────────────────────────────────────────────────────────────────────────
  ❌ 个人脚本引入企业级日志:
    const logger = winston.createLogger({
        level: 'info',
        format: winston.format.combine(
            winston.format.timestamp(),
            winston.format.json()
        ),
        transports: [ new winston.transports.File({ filename: 'app.log' }) ]
    })
  ✅ 个人脚本:
    console.log('Processing:', args)
────────────────────────────────────────────────────────────────────────────────
1.10 设计模式滥用
────────────────────────────────────────────────────────────────────────────────
  触发信号:「使用 XXX 模式可以…」
  ❌ 简单 if/else 被强行包装成策略模式(Python 场景):
    class SortStrategy(ABC):
        @abstractmethod
        def sort(self, arr): ...
    class BubbleSort(SortStrategy):
        def sort(self, arr): ...
    class Sorter:
        def __init__(self, strategy: SortStrategy): ...
    # 实际只调用一次,排序算法固定为冒泡
  ✅ 实际需要:
    arr.sort()
────────────────────────────────────────────────────────────────────────────────
1.11 过度的安全加固
────────────────────────────────────────────────────────────────────────────────
  ❌ 内网 CLI 工具加了公网级防护:
    app.use(helmet())
    app.use(rateLimit({ windowMs: 15 * 60 * 1000, max: 100 }))
    app.use(cors({ origin: process.env.ALLOWED_ORIGINS?.split(',') }))
  原则:安全措施应针对真实的攻击面,而非想象的攻击面。
────────────────────────────────────────────────────────────────────────────────
1.12 架构提前复杂化(Big Design Up Front)
────────────────────────────────────────────────────────────────────────────────
  Gall's Law:「能运作的复杂系统都从能运作的简单系统演化而来,
  跳过简单阶段直接设计复杂系统的尝试,从来不会成功。」
  ❌ MVP 阶段直接设计微服务:
    用户服务 / 订单服务 / 通知服务 / API 网关 / 消息队列 / 服务发现...
  ✅ MVP 应该是:
    一个应用 + 一个数据库,跑通核心流程再演进。
    (何时演进 → 见第六章 6.6 演进触发条件)
────────────────────────────────────────────────────────────────────────────────1.13 用复杂度对冲不确定性(Claude 特有模式,最核心)
────────────────────────────────────────────────────────────────────────────────
  这是 Claude 独有的过度工程模式,人类工程师极少这样做。
  【机制】
  当 Claude 不确定如何干净地实现某个功能时,它会通过增加抽象层来
  "保留退路":接口可以换实现,工厂方法可以切换策略,配置项可以在
  运行时调整。这些抽象不是为你服务的,是为 Claude 自己的不确定性
  服务的。
  【Claude 特有的表现形式】
  · 给出一个 Claude 自己也无法解释"为什么要这样"的复杂结构
  · 解释听起来很合理("这样更灵活"),但追问具体场景时开始模糊
  · 实现中包含多个"可选扩展点",但你从未要求过扩展性
  · 方案里有一层或多层"中间件",职责是纯转发
  【识别方法】
  追问:「如果去掉这层抽象,会发生什么具体问题?」
  如果 Claude 的回答变得模糊,说明这层抽象是不确定性的护身符。
  ❌ 触发信号:
    「我设计了一个 Pipeline 结构,这样各步骤可以灵活组合…」
    (你只需要顺序执行 3 个步骤,而这 3 个步骤从来不需要重新组合)
  ► 专项干预:
    「你的方案是否是因为你不确定这段逻辑最终长什么样,
     所以用抽象层保留了灵活性?如果是的话,请告诉我你不确定的地方,
     我们先确定需求,再写代码。」
    (→ 使用模板 4 挖掘不确定性根源)
────────────────────────────────────────────────────────────────────────────────
1.14 测试过度工程
────────────────────────────────────────────────────────────────────────────────
  过度工程不只发生在实现代码里,测试里同样常见。
  ❌ Claude 倾向给出:
    · Mock 一切(包括不需要 mock 的内部函数)
    · 测试实现细节而非行为(断言内部变量的值,而非函数的输出)
    · 为每个私有方法写单独的测试
    · 100% 覆盖率的强迫症(覆盖了永远不会出错的 getter/setter)
    · 设置 / 拆除代码比实际测试代码还长
  ✅ 好的测试:
    · 测试行为(给定输入,验证输出),不测试实现
    · 只 mock 外部依赖(网络、数据库、时钟)
    · 测试对重构透明——你重构实现,测试不需要改
  ► 干预句式:
    「你的测试是在测试这个函数"怎么实现的"还是"做了什么"?
     如果我重构实现但保持行为不变,这些测试需要改吗?
     如果需要,说明测试耦合了实现细节,请重写。」
────────────────────────────────────────────────────────────────────────────────
1.15 修复过程中的范围蔓延(Scope Creep in Repair)
────────────────────────────────────────────────────────────────────────────────
  与 1.5(不请自来的重构)的区别:
  1.5 是"修改时顺便重构",是风格上的扩展。
  1.15 是"修复 BUG 时把修复范围越扩越大",Claude 会声称这些都是
  "BUG 的根本原因"或"必要的修复",因此比 1.5 更难拒绝。
  ❌ 你要修一个变量名拼写错误,Claude 给出:
    「问题根源在于整个模块的状态管理方式。我将:
     1. 修复拼写错误(你要的)
     2. 重构状态管理为 Redux 模式(「防止类似问题」)
     3. 加入单元测试(「确保修复有效」)
     4. 更新接口定义(「保持一致性」)」
  ✅ 你要修拼写错误,Claude 只改那一个拼写错误。
  【关键判断】:1~3 是真的 BUG 原因?还是 Claude 趁机把待办清单里
  的"改进项"塞进来?追问:「拼写错误修好之后,2/3/4 各自单独
  会在什么地方出什么 BUG?」
  ► 干预句式:
    「只修复这一个 BUG,其他所有"改进"算作独立任务,
     现在不做。修复完成后,我来决定是否处理那些改进。」
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
01:29
官方阅,申请积分计划2,希望官方继续支持我完成这款游戏,截图
官方阅,申请积分计划2,希望官方继续支持我完成这款游戏,
视频内容只是一部分, 本游戏耗时3个月,目前完成进度百分之80, 是生存游戏,进入修仙界,走剧情找到宗门加入, 这时游戏才是真正开始, 提升实力境界后就可以变强,获取功法法术法宝, @视频内是游戏里挑战妖族入侵一种主流玩法,游戏就是围绕着这个来进行, 还有很多地方可以战斗,获得资源修炼变强,比如去藏书阁学习功法, 去法宝楼抽法宝,每一个宗门数十个法宝抽取 去修仙界探索,获得各自的资源,可能遇见妖兽
1 赞
3 回复
本地部署 AI 对接 TapMaker 指南 —— 以 CodeBuddy 为例V1.1截图
本地部署 AI 对接 TapMaker 指南 —— 以 CodeBuddy 为例V1.1
写在前面 大家好,我是橘猫,和你一样也是TapMaker的萌新玩家。在"全能神"天哥的悉心指导下,我顺利完成了本地开发环境的部署。经过这段时间的实战测试,已经成功打通了「本地开发 → 同步至TapMaker」的完整流程。 以下内容全部来自我的个人实操经验,旨在为同样在探索本地部署的朋友提供一个参考。每个人的电脑环境、网络情况、AI工具版本都不尽相同,文中的步骤仅供交流学习。如果你照着操作后遇到问题
24 赞
14 回复
【UI教程】如何将已有的效果图应用为实际的UI界面截图
【UI教程】如何将已有的效果图应用为实际的UI界面
在经过了一些折腾和比较折磨的尝试后,我总算是摸清楚了嗒啦啦怎么把UI效果图转换为实际游戏中的UI组件,今天就给大家带来这部分的经验分享。 tips:1.本篇教程需要各位掌握最基本的ps使用,具体的操作部分我会大致讲解,但仍需各位自行学习ps的基本操作,部分可以由ai代劳的环节我会注明。 2.本篇教程需要在以我前两篇教程作为前置环节,请在阅读这两篇前置教程后再进行本篇教程内容的学习 在按照前
10 赞
4 回复
新人避坑指南第一期(核心必看)截图
新人避坑指南第一期(核心必看)
新手制作游戏项目三大避坑准则 一、前期地图规范要求 开启新项目之后,必须清晰交代需求:明确项目内容、运行环境、角色出生点位置,再交由助手制作第一张地图。 第一张地图禁止直接预览,先将生成内容存入素材库,核对样式是否符合自身预期。 核心判定方法:单独生成第一张地图预览图,第一张地图决定整体全局架构,UI、UX整体风格全部由它锁定。如果第一张地图的画面、UI、UX不符合自己的设想,立刻新建项目,不要在
9 赞
2 回复
2D 等轴测视角:完整理论截图
2D 等轴测视角:完整理论
2D 等轴测视角:完整理论 一、视角的本质 什么是等轴测 人站在高处斜着往下看地面,地面上的方格子不再是正方形,而变成了菱形。这就是等轴测的视觉本质。 俯视(正上方看下去): 等轴测(斜上方看下去): ┌──┬──┬──┐ ◇ ├──┼──┼──┤ ◇ ◇ ├──┼──┼──┤ ◇ ◇ ◇ └──┴──┴──┘ ◇ ◇ ◇ 正方形网格经过旋转 + 压缩,变成了菱形网格。 为什么是 2:1
6 赞
别再烧积分了!从每次 2000 到每次 50 的血泪经验截图
别再烧积分了!从每次 2000 到每次 50 的血泪经验
适用场景:所有在用 TapTap Code 开发游戏的小白 难度:★☆☆☆☆ 背景最近群里总有人"炫耀"一次操作花了几千积分,说实话这不是值得高兴的事——这是在告诉所有人你的开发方式有根本性问题。我也走过这条弯路,所以来说说怎么改。 积分消耗的本质是什么积分 = AI 处理的 token 数量 = 你发给 AI 的内容 + AI 回给你的内容所以烧积分的本质只有两种: 你让 AI 做了大量无效/重
精华
64 赞
20 回复
如何提升你游戏中的UI美术水平截图
如何提升你游戏中的UI美术水平
一、请为你的游戏挑选一款合适的字体 很多开发者没有注意到其实UI界面中最重要的元素是字体,一款合适的字体能给整个游戏的界面感官带来蜕变。 请看案例 那么如何挑选适合自己的字体呢? 我总结出了一些小经验可供参考: 黑体:通用 宋体:古风、武侠、修仙 楷体:古风、武侠、修仙 圆体:卡通、动漫、Q版 科技:科幻、未来、电子 顺手分享一个免费可商用字体网站: 当然 如果你不知道自己的游戏适合什么风格
精华
117 赞
36 回复
[开发心得]让塔拉拉帮你的2D游戏做个动作编辑器(KEIS)截图
[开发心得]让塔拉拉帮你的2D游戏做个动作编辑器(KEIS)
先叠甲:笔者没有引擎开发经验,此处提供一个思路,希望我能抛砖引玉让大佬们发现更强的办法大家一起进步;(实在是可以优化的空间还很多,实则我积分告急了[表情_吐舌头]) 文字太多不想看的读者,文章底部有伪焚诀可以自取 正在用塔拉拉做一个武侠游戏,但觉得无法编辑动作对于武侠游戏多少是个硬伤, 如果绘制大量精灵图又无法角色通用,同时对于我的美术需求量也会暴涨; //提炼我的需求:各角色通用,且不会增加
精华
23 赞
5 回复
00:15
科研了一下嗒啦啦生成spine截图
科研了一下嗒啦啦生成spine
做图标动态或者转场动态这种图形类动画应该没问题,可以做到这个效果,人物动作的话不太行。 尝试做了可视化,引擎里没法实时更新创建骨骼,也用不了网格,还是得用spine软件。微调位置和动态效果幅度时间之类的可以 拆分建议自己做,复杂形状嗒啦啦有点拆不明白
23 赞
13 回复
自己做的一款游戏截图
自己做的一款游戏
完整游戏设定(严格按你全部要求整理,无修改原版台词、猛虎大招、隐藏捷径路线) 基础总设定 写实第三人称3D剧情格斗,流畅打斗动作,主角大招:猛虎变身(匹配泰格先锋军虎机甲) 场景:郊外空地、牢狱 角色:兽=荒野行动泰格先锋军机甲;主人格=纯白简约白衣 核心规则:玩家自由选择常规主线/隐藏捷径路线 第一章:分离宿命(第1关) 隐藏捷径触发条件(隐藏路线) 地图4个石墩点位,站石墩
4 赞
2 回复