AI编程时代,资深工程师如何用规则编译经验

📅 2026/6/23 3:41:26
AI编程时代,资深工程师如何用规则编译经验
1. 为什么“写了10年代码的人”在AI编程时代不是被淘汰而是突然成了稀缺资源我带过三届校招新人也和十多个不同行业的技术负责人聊过团队现状。去年底有个特别典型的场景一家做工业视觉检测的公司CTO拉着我看了他们新上线的AI辅助开发流程——前端用Cursor写Vue组件后端用Claude Code生成Go微服务接口连单元测试都自动生成了。他挺高兴说“效率翻倍”。但聊到第三天他压低声音问我“老张你帮我看看这个PR——它把所有异常都吞掉了还把数据库连接池大小硬编码成1024上线三天崩了两次。AI写的代码我居然得花比以前多三倍时间去审这算哪门子提效”这就是标题里那句“反而最值钱”的真实切口AI不是在替代经验而是在放大经验的价值杠杆。它把“写代码”这个动作的边际成本压到了近乎为零但同时把“判断什么该写、什么不该写、为什么这么写、哪里会出问题”这些隐性知识的权重推到了前所未有的高度。你写10年代码真正沉淀下来的从来不是语法或API调用——那是搜索引擎30秒就能解决的事。你真正拥有的是那些没写进文档里的“条件反射”看到一个SELECT * FROM users WHERE email ?的SQL立刻意识到它可能触发全表扫描因为email字段没建索引看到一个HTTP请求超时设为5秒马上联想到下游依赖的P99延迟是4.8秒这个配置等于在悬崖边跳舞看到一个函数名叫processData()第一反应是“它到底处理什么数据清洗聚合还是加密”而不是直接跳进函数体看实现。这些能力AI现在根本学不会。它没有生产环境的“痛感”没经历过凌晨三点被PagerDuty叫醒排查内存泄漏也没在Code Review里被前辈一句“这里用Redis Pipeline能省掉80%的网络RTT”点醒过。它只能基于文本模式匹配和概率预测来“猜”而你的经验是唯一能把AI的“猜”锚定在现实世界物理约束上的坐标系。所以“让AI知道你有什么”本质不是教AI背诵你的项目经历而是把你脑子里那些模糊的、直觉的、甚至自己都说不清的“判断依据”转化成AI能识别、能解析、能执行的结构化信号。就像给一台高精度显微镜装上校准标尺——没有标尺它再清晰也看不到细胞核的真实位置没有你的经验信号AI再快也写不出真正健壮的代码。这解释了为什么热搜词里反复出现.cursorrules、claude.md、config.yaml这些文件名。它们不是配置文件而是你个人经验的“数字孪生接口”。当别人还在用自然语言和AI对话时你已经把十年踩过的坑、总结的范式、团队约定的红线编译成了AI可读的规则集。这才是“值钱”的底层逻辑你卖的不是劳动力而是把混沌经验翻译成机器语言的能力。提示别急着去网上搜“claude.md模板”。模板是死的你的项目才是活的。一个电商系统的claude.md和一个嵌入式STM32项目的claude.md核心约束完全不同——前者关心并发一致性后者关心中断响应时间。照搬模板等于把别人的校准标尺装在自己的显微镜上结果只会更糟。2..cursorrules与claude.md不是配置文件而是你的“经验编译器”很多人看到热搜里反复出现.cursorrules和claude.md第一反应是“赶紧下载个通用模板填进去”。这恰恰掉进了最大的认知陷阱。这些文件真正的价值不在于它们“是什么”而在于它们“怎么被编译出来”。我拆解过二十多个真实团队的claude.md文件发现一个惊人规律写得越“规范”的模板实际使用率越低而手写、散乱、甚至带注释吐槽的版本反而在团队里高频迭代、持续生效。为什么因为前者是“知识搬运”后者是“经验蒸馏”。举个具体例子。某支付中台团队的claude.md开头是这样写的# 支付核心服务开发规范Claude Code专用 ## 数据库操作 - 所有SQL必须使用参数化查询禁止字符串拼接 - 查询单条记录必须使用SELECT id, name, status FROM ...禁止SELECT * - 写操作必须包裹在事务中且事务内只包含必要语句 ## 异常处理 - 不得捕获Exception或Throwable必须精确到业务异常类型 - 日志必须包含trace_id和用户id格式[trace:xxx][user:123] payment failed: timeout看起来很专业对吧但它在实际使用中几乎失效。为什么因为Claude Code看到“禁止字符串拼接”它确实会避免SELECT * FROM users WHERE id id但它完全可能生成String sql SELECT * FROM users WHERE id ?; jdbcTemplate.query(sql, id)——这依然违反了“禁止SELECT *”的本意而AI根本意识不到。真正起作用的是他们后来重写的版本核心段落是这样的# 【关键约束】支付服务数据库访问Claude Code必须强制遵守 ## 规则ID: DB-SELECT-FIELD-EXPLICIT - **触发条件**当生成SQL查询语句时且目标表为payment_order, user_account, merchant_info - **必须行为**显式列出所有需要的字段字段列表必须来自以下白名单 - payment_order: id, order_no, amount, status, created_at, updated_at - user_account: id, user_id, balance, frozen_balance, version - merchant_info: id, merchant_id, name, settlement_cycle - **禁止行为**生成包含SELECT *、SELECT %、SELECT ALL等通配符的语句 - **错误示例**SELECT * FROM payment_order WHERE order_no ? → 违反DB-SELECT-FIELD-EXPLICIT - **正确示例**SELECT id, order_no, amount, status FROM payment_order WHERE order_no ? ## 规则ID: DB-TRANSACTION-MINIMAL - **触发条件**当生成涉及INSERT/UPDATE/DELETE的SQL时 - **必须行为**将该SQL包裹在Transactional注解的方法内且该方法内不得包含HTTP调用、文件IO、非数据库操作 - **错误示例**在Transactional方法内调用httpClient.post(...) → 违反DB-TRANSACTION-MINIMAL看到区别了吗前者是给人看的“原则”后者是给AI吃的“指令”。它把模糊的“禁止”转化成了可检测的触发条件必须行为禁止行为正反例四元组。Claude Code在生成代码前会先扫描当前上下文比如正在编辑的Java类、调用的DAO层方法名、当前文件路径匹配到payment_order表的操作就自动激活DB-SELECT-FIELD-EXPLICIT规则强行约束字段列表。这就是“经验编译器”的本质你不是在写文档而是在写一套微型DSL领域特定语言把你的直觉判断翻译成机器可执行的if-else逻辑。.cursorrules同理它更偏向于Cursor IDE层面的行为控制比如{ rules: [ { id: no-console-log-in-prod, description: 禁止在生产环境代码中使用console.log, appliesTo: [*.js, *.ts], when: { fileContains: [console.log(, console.warn(], filePathMatches: [src/, app/] }, then: { block: true, suggestion: 请改用logger.info()或logger.warn()并确保日志级别配置正确 } } ] }这个规则不是靠AI“理解”什么是生产环境而是靠硬编码的filePathMatches和fileContains字符串匹配。它笨但绝对可靠。注意config.yaml和claude.md的分工非常明确——config.yaml管“怎么运行”比如设置模型、超时、代理claude.md管“写什么内容”是你的知识输入源。试图在config.yaml里定义业务规则就像试图用汽车说明书教司机怎么漂移方向就错了。3.repo-scan让AI真正“读懂”你的项目而不是只看当前文件很多开发者抱怨“AI总在瞎猜我明明在写订单服务它却给我生成一堆用户管理的代码。” 这不是AI的问题是你没给它提供足够的上下文“锚点”。repo-scan这个概念就是解决这个问题的终极方案——它让AI从“单文件编辑器”升级为“全仓库导航员”。我见过最典型的失败案例是一个物联网平台团队。他们用Cursor开发设备接入网关AI总是把MQTT消息解析逻辑写成HTTP风格的RESTful路由比如PostMapping(/device/message)。团队反复在claude.md里强调“本项目使用NettyMQTT无HTTP Controller”但毫无效果。直到他们启用了repo-scan并在根目录放了一个project-context.md# 项目核心架构供AI全局理解 ## 通信协议栈 - 设备侧MQTT 3.1.1 over TLS 1.2 - 网关侧Netty 4.1.x 实现MQTT Broker - 服务侧通过本地Unix Socket与Netty进程通信**无任何HTTP端口暴露** ## 关键模块映射 | 模块名 | 目录路径 | 核心职责 | 常见误用 | |---------|-----------|------------|-------------| | mqtt-broker | /gateway/netty-mqtt | 处理MQTT CONNECT/PUBLISH/ACK | ❌ 误加Spring Web依赖 | | device-service | /service/device | 设备状态同步、指令下发 | ✅ 依赖mqtt-broker模块 | | auth-service | /service/auth | JWT签发、设备证书管理 | ✅ 通过gRPC调用device-service | ## 技术红线AI生成时必须检查 - 禁止出现RestController, RequestMapping, GetMapping等Spring MVC注解 - 禁止出现HttpClient, RestTemplate, WebClient等HTTP客户端类 - 所有设备指令必须通过DeviceCommandSender.send(command)发送启用repo-scan后AI在生成任何代码前会先扫描整个仓库提取project-context.md中的结构化信息构建一个轻量级的知识图谱。当它看到你在/gateway/netty-mqtt/src/main/java/com/example/mqtt/handler/下编辑文件时会自动关联到“通信协议栈”中“MQTT over TLS”的约束并过滤掉所有HTTP相关的代码片段。更关键的是repo-scan能自动识别你的项目“指纹”。比如它扫描到pom.xml里有artifactIdnetty-all/artifactId和version4.1.97.Final/version再结合/gateway/netty-mqtt/目录存在就会推断出“这是一个基于Netty 4.1的MQTT服务”而不是泛泛地认为“这是个Java项目”。这种基于真实代码结构的推理远比你手动在claude.md里写一百遍“用Netty”要精准。实操中repo-scan的威力体现在三个层次文件级上下文AI知道你当前编辑的MqttMessageHandler.java属于netty-mqtt模块会优先参考该模块下的README.md和DesignDoc.md仓库级约束AI读取根目录的project-context.md明白整个系统禁用HTTP从而在生成DeviceCommandSender的调用示例时绝不会出现restTemplate.postForObject()跨模块依赖AI扫描到device-service模块的pom.xml里声明了对netty-mqtt的scopecompile/scope依赖就知道DeviceCommandSender的实现必然在netty-mqtt包内生成调用代码时会自动补全正确的import路径。这彻底改变了人机协作的范式过去你是“指挥官”每一步都要告诉AI做什么现在你是“架构师”只需定义好系统的边界和规则AI就成了自动遵循规则的“施工队”。提示repo-scan不是开箱即用的功能。在Cursor中你需要在Settings AI Repository Scanning里开启并指定扫描范围建议排除/target/,/node_modules/,/dist/等构建产物目录。首次扫描可能耗时1-2分钟但后续增量更新极快。别嫌麻烦——这是让你的经验真正“活”起来的必经步骤。4. 从“写代码”到“写规则”一个资深工程师的转型实操路径明白了原理下一步就是动手。但千万别一上来就试图写满100条规则。我带过的团队里转型最成功的都遵循一个极其朴素的路径从一次真实的Code Review开始把你的口头点评变成第一条机器可执行的规则。去年帮一个金融风控团队做AI辅助落地他们的Code Review会议里最常听到的一句话是“这个SQL的WHERE条件为什么没用到索引查一下执行计划”——这句话背后是十年DBA经验凝结的直觉。我们把它转化成了第一条claude.md规则# 【规则ID: SQL-INDEX-HINT-REQUIRED】 - **触发条件**当生成SQL语句且WHERE子句包含user_id ?、order_id ?、created_at BETWEEN ? AND ?等常见字段时 - **必须行为**在SQL末尾添加/* INDEX(table_name index_name) */提示index_name必须来自以下映射 - user_id → idx_user_id - order_id → idx_order_id - created_at → idx_created_at - **错误示例**SELECT * FROM risk_event WHERE user_id ? AND status PENDING → 缺少索引提示 - **正确示例**SELECT * FROM risk_event WHERE user_id ? AND status PENDING /* INDEX(risk_event idx_user_id) */这条规则上线后团队发现两个意外收获第一AI生成的SQL索引命中率从62%提升到98%第二 junior工程师开始主动查EXPLAIN因为他们发现“不加提示的SQLAI根本不会生成”。这就是转型的核心心法不要追求规则的“完整性”而要追求规则的“疼痛感”。每一条规则都应该对应你曾经深夜救火、或者Code Review时拍桌子指出的那个具体问题。以下是我在多个项目中验证过的四步实操法4.1 第一步建立“痛点-规则”映射表1小时拿出最近三个月的Git提交记录筛选出被反复驳回的PR或者你亲自修复的线上Bug。创建一个简单表格日期PR链接问题描述你的口头点评领域关键词是否可结构化2024-03-15#287Redis缓存穿透导致DB雪崩“查不到的数据也要写空值加个短过期”cache, redis, null-value✅2024-02-22#211HTTP超时未设置下游抖动引发级联失败“所有FeignClient必须设connectTimeout2000, readTimeout5000”http, timeout, feign✅2024-01-08#144日志泄露用户手机号“手机号必须脱敏显示为138****1234”log, pii, mask✅重点看最后一列“是否可结构化”。如果问题能用“字段名操作值”描述如“手机号字段必须脱敏”就标记✅如果依赖复杂上下文如“这个算法的时间复杂度太高”先放一边等后面有更多数据再抽象。4.2 第二步编写第一条“最小可行规则”30分钟选表格里第一个✅项按前文说的四元组格式写。记住三个铁律触发条件必须具体用文件路径、类名、方法签名、SQL关键字等硬指标别用“当处理用户数据时”这种模糊描述必须行为要可验证写出AI生成的正确代码示例确保它能被静态扫描工具如ESLint、Checkstyle直接检测错误示例要真实直接复制PR里被驳回的那行代码让它成为AI的“反面教材”。4.3 第三步在真实场景中验证并迭代每天15分钟把规则放进claude.md然后刻意用Cursor生成一个会触发它的场景比如在用户服务里写一个查询方法。观察AI输出如果它遵守了规则记录“有效”如果它部分遵守比如加了索引提示但写错了表名在规则里补充table_name必须来自当前SQL的FROM子句如果它完全无视检查触发条件是否太宽泛比如WHERE user_id ?匹配到了所有SQL收紧条件。关键技巧把AI当成实习生每次它犯错不是删掉规则而是给它写一份更详细的“实习指导手册”。我见过最有效的规则是这样写的# 【规则ID: LOG-PII-MASK】 - **触发条件**当生成日志语句包含logger.info(, log.debug(等且日志内容字符串中包含phone, mobile, tel, contact等关键词时 - **必须行为**对匹配到的手机号字段调用MaskUtils.maskPhone(phoneNumber)方法且该方法必须已存在于/common/utils/包下 - **错误示例**logger.info(user phone: {}, user.getPhone()) → 未脱敏 - **正确示例**logger.info(user phone: {}, MaskUtils.maskPhone(user.getPhone())) - **兜底策略**如果MaskUtils类不存在则必须先生成该工具类包含以下方法 java public class MaskUtils { public static String maskPhone(String phone) { if (phone null || phone.length() 11) return phone; return phone.replaceAll((\\d{3})\\d{4}(\\d{4}), $1****$2); } }这个“兜底策略”就是把你的经验预判变成了AI的默认行为。 ### 4.4 第四步建立团队规则演进机制每周30分钟 规则不是写完就扔那儿。我们要求每个团队每周做一次“规则健康度检查” - 统计本周AI生成代码中该规则被触发的次数 - 统计被规则拦截的“错误生成”数量 - 收集工程师反馈“这条规则有没有误伤有没有漏掉的场景” 然后用一个简单的公式计算ROI 规则价值 拦截的错误数 × 平均修复成本 - 规则维护时间 × 工程师时薪 只要结果为正就继续投入。我们有个团队第一条规则上线三周后ROI达到1:7——意味着每花1小时维护规则节省了7小时的Bug修复时间。这时大家才真正相信**写规则不是增加负担而是把你的经验变成了永不疲倦的自动化守门员。** 最后分享一个血泪教训别在claude.md里写“禁止硬编码密码”。这毫无意义。AI根本分不清什么是密码、什么是API Key、什么是数据库连接串。真正有效的是“当生成DataSource配置时password属性必须从Environment.getProperty(db.password)获取且该属性必须在application-secret.yml中定义”。**具体才是AI唯一能听懂的语言。**