ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

AGENTS.md 实战指南:如何写好 AI 编程的项目配置

AGENTS.md 实战指南:如何写好 AI 编程的项目配置 AGENTS.md 这个东西最近在 AI 编程圈子里确实是绕不开的话题。我自己从开始给项目补上这个文件到现在差不多一年前后迭代了好几版踩过不少坑也总结出一套相对稳定的写法。很多人以为它就是给 AI 助手看的说明文档但实际上写好了它能让 Claude、Cursor 这些工具在项目里的表现直接上一个台阶写不好AI 照样满嘴跑火车改一行代码能给你把整个架构掀翻。这篇文章就把我实际在用的 AGENTS.md 写法完整拆开讲一遍不只是模板还包括为什么这么写、每个字段怎么填、填多少合适以及那些文档里不会告诉你的细节。适合正在用 AI 辅助编程的人无论你是个人开发者还是团队里负责搭基建的都可以直接照着抄。1. 先搞清楚 AGENTS.md 到底是干嘛的1.1 它和 README 的本质区别很多人觉得 README 就够了AI 自己会看。这个想法我一开始也有后来发现完全不是一回事。README 是写给人看的它的目标是让一个新加入的人类开发者在 10 分钟内知道这个项目是做什么的、怎么跑起来、目录结构什么样。但人类会主动联想知道哦这个模块是负责支付回调的然后自己去看对应代码AI 不会它更像一个读了很多书但完全没有常识的实习生——你把 README 丢给它它知道命令怎么敲但完全不知道这个项目的潜规则、边界、雷区。AGENTS.md 的本质是给 AI 的一份项目本地化配置。它的作用是告诉 AI这个项目里哪些事能做哪些事绝对不能做改代码前要先看哪个文件测试跑哪条命令代码风格是什么样的遇到什么情况不要自作主张。你可以把它理解成 AI 进项目之前的入职培训手册。1.2 没有 AGENTS.md 时 AI 的表现我来说几个实际遇到的场景你感受一下。有一段时间我在做一个 FastAPI 的数据服务项目里配了 Ruff 做 lint 和格式化行宽设的是 100。但 AI 生成的代码默认是 88Black 的默认值而且特别喜欢把函数签名拆成多行。每次我让它加个接口它都会顺手“美化”一遍我原有的代码diff 里一半是逻辑改动一半是格式改动review 的时候烦得要死。还有一次项目里有个约定所有数据库查询必须走 repository 层禁止在 service 里直接写 SQLAlchemy 的 session 查询。AI 不知道这个约定它看到 model 定义就直接 query看起来功能实现了但代码风格跟整个项目格格不入后续维护的人看了会骂人的。最典型的还是测试问题。很多项目的测试命令不是简单的 pytest而是需要先起一个测试数据库或者要带特定的环境变量。AI 执行测试跑不出来它不会去查是不是环境问题而是直接“修”测试代码越修越错。这些问题的根源只有一个——AI 不了解项目上下文。AGENTS.md 就是用来补上这个上下文的。2. 写 AGENTS.md 前先想清楚四件事2.1 明确读者是 AI不是人写之前最重要的一件事放下写给人看的习惯。AI 读文件的方式跟人不一样它不会像人那样翻完整个文件然后提炼重点而是按需读取。现在主流的 AI 编码工具都支持切片读取也就是文件技能只读取和你当前任务相关的部分。这意味着文件结构要足够清晰小标题明确方便 AI 做语义检索每个小节只讲一件事不要混在一起绝对忌讳写一大段散文AI 检索到其中一句可能把整段的上下文都误解了我见过有人把 AGENTS.md 写成一篇 2000 字的散文文笔很好逻辑也清晰但 AI 用了等于没用。因为它没法在对话中一次性消化这么多内容而且检索时抓到的片段往往不是最关键的。2.2 内容和信息量做减法第二件事是控制内容量。AGENTS.md 不是越全越好而是越精越有效。这里面有个机制问题AI 的上下文窗口是有限的且每个 token 都可能是干扰信息。你把全项目的原理都写进去AI 在处理一个“给某个接口加参数”的小任务时会被大量无关信息干扰判断。我的经验是一个项目的 AGENTS.md 保持在 200 到 400 行左右比较合适。超过 600 行AI 的遵守率会明显下降低于 100 行又往往覆盖不到什么有效信息。有一个具体的取舍原则只写那些违反后不会报错、代码能跑、但不符合项目规范的内容。比如格式规范、分层规范、命名规范、不变量约束。这些是 AI 最容易犯的错也是人不容易发现的问题。反而是那些不这样写就会报错的内容不需要写AI 犯错了自己会通过报错修正。2.3 想清楚放仓库哪里AGENTS.md 可以放在仓库的多个层级仓库根目录影响整个项目的所有任务子目录比如 src/backend/AGENTS.md只影响该目录下的任务docs/ 下面一般需要特殊配置才会被 AI 读取不建议最优实践是根目录放一个总纲然后在代码密度高的子目录放针对性更强的局部文件。比如一个 monorepo 里有前端、后端、算法三个模块根目录写通用的协作规范和命令每个模块目录下再写一份自己的 AGENTS.md讲本模块的架构约束和特有命令。我现在的项目就是这么干的实测下来比所有内容都塞根目录要好用得多。局部文件之间不需要重复写通用规范AI 读取时会自动合并上下文。2.4 把它当代码维护不当事后总结这是我最想强调的一点。AGENTS.md 不是写一次就完事的它需要跟代码同步演进。我的做法是每完成一个重要的架构调整顺手更新 AGENTS.md每发现 AI 反复犯同一个逻辑错误就在禁忌与陷阱里加一条每次新建了 npm script 或 Makefile 指令也同步更新命令列表。这套文件最好放在和代码同一个 MR 里修改review 的人能一起看。我自己现在把更新 AGENTS.md 当成项目里的一部分工作量来估不把它排除在看板之外——考虑到它对整体效率的杠杆作用这样做很值得。3. 一份靠谱的 AGENTS.md 应该长什么样3.1 头部用最短的话锁住 AI 的行为基调文件开头要有一个很短的“项目自我介绍 行为基调”三到五行为宜。这段的价值在于让 AI 在进入项目的第一时间就进入状态。我用的是一个标准格式# AGENTS.md ## Project Overview FastAPI 数据服务负责用户行为数据的采集、清洗与查询。 面向数据分析师提供服务稳定性要求高于功能丰富度。 ## Developer Guide - AI 必须遵守现有架构模式不得擅自引入新的框架或组件 - 所有改动必须保持向后兼容注意这里面我不去描述“项目是做什么的”这种泛泛信息而是直接强化两个约束别乱引框架、别破坏兼容性。这两条是历史教训的浓缩——AI 最喜欢干的事就是为了实现一个小功能给你引一个 holger 库进来。3.2 项目速览让 AI 三分钟找到门接下来是项目速览包括## Project Structure - src/api/ — 路由层只负责 HTTP 参数解析与响应封装 - src/service/ — 业务逻辑层禁止直接操作数据库 - src/repository/ — 数据访问层所有数据库操作必须经过此层 - src/models/ — SQLAlchemy ORM 模型定义 - tests/ — Pytest 测试按模块路径镜像 src 目录这一段的作用是给 AI 画一张地图。它不需要详细到每个文件干什么只要到目录粒度就行。重点是把层次依赖关系写清楚比如“路由调 serviceservice 调 repository”这能防止 AI 越层调用。项目速览里还需要包含技术栈版本## Tech Stack - Python 3.11 / FastAPI / SQLAlchemy 2.x / Alembic - PostgreSQL 15 / Redis 7 - Ruff (lint format) / Pytest / Locust版本信息很重要。比如 SQLAlchemy 2.x 和 1.x 的 query 写法完全不同AI 训练数据里老版本占大多数不写明版本它就倾向写老 API一堆兼容性问题。3.3 命令速查表给 AI 一套不会出错的工具箱这一节要覆盖 AI 在项目里可能用到的所有命令包括开发、测试、lint、构建。这是最容易写也最容易被忽视的部分但它解决的问题非常实际问题——消解“AI 瞎猜命令”。我的模板是## Commands - Run dev server: uvicorn src.main:app --reload - Run tests: pytest tests/ -x -q - Run lint: ruff check src/ tests/ - Auto-fix lints: ruff check --fix src/ tests/ - Run a single test: pytest tests/test_xxx.py::test_name -x -q - Database migration: alembic upgrade head - Generate migration: alembic revision --autogenerate -m desc有几个细节要说明第一测试命令里我加了-x这个是失败即停因为 AI 跑测试时如果你不限制它可能跑完所有用例输出超级长上下文被占满反而影响判断。-q是安静模式减少输出噪音。第二lint 命令一定要写清楚用什么工具。很多项目同时有 flake8、black、isort、ruffAI 默认会去调 black而你项目里用的是 ruff格式规则并不完全一样。你给 AI 一个确定的命令它就少一步猜。第三对于那些需要外部依赖才能跑的命令一定要写前提条件。比如依赖数据库的测试你要写 “Ensure local PostgreSQL is running, then run...”不然 AI 会对着连接失败的结果开始瞎改代码。3.4 代码风格不写黑话只写能让 AI 少犯错的规则代码风格这一节是最有分量的。要顶住“AI 随手写代码”的诱惑——它训练集里的代码风格是全网的平均风格不是你项目的风格。写的时候不必覆盖所有风格写最关键的三点## Code Style - 行宽 100使用 Ruff 默认规则不要手动换行把参数列表拆成多行 - 类型标注必须完整所有函数参数和返回值必须写类型注解 - 禁止在业务代码中使用全局变量配置统一从 Settings 读取为什么这些关键类型标注这一条AI 在中小项目上特别喜欢省略因为训练数据里很多示例代码为了短都不写。但一个数据服务项目类型标注是后期维护的命根子。还有一个值得写的风格指令是 import 的组织方式- import 顺序标准库 → 第三方 → 项目内模块每组之间空行这条 AI 基本不会遵守除非你写在 AGENTS.md 里。但你没写的时候它乱排 import 很影响阅读习惯。至于“不要手动拆行”这条是因为我吃过亏AI 为了美观常把函数签名强行拆成一行一个参数导致本来就紧张的行数被白白浪费diff 变得很大。写清楚这条之后生成的代码简洁多了。3.5 任务执行规范告诉 AI 改代码前做哪些事比起告诉 AI“怎么写”我认为更关键的是告诉它“改代码的顺序”。因为 AI 最欠揍的地方在于你让它加一个功能它直接改文件、生成代码、结束。不加日志不写测试不验证效果。这部分我建议这样写## Workflow Rules - 修改代码前先运行 git status 和 git diff理解当前分支的改动范围 - 实现功能后必须为该功能补充或更新对应测试 - 涉及数据库结构的改动必须同步生成 Alembic migration - 运行测试被要求前先跑 pytest tests/ -x -q 做快速验证 - 所有改动必须遵守现有日志规范使用 structlog禁止 print 调试这几条看着简单但每一句都在解决一个具体问题。拿“先看 git diff”来说我遇到过多次这样的场景我改了一部分代码还没改完让 AI 接着改另一个人文件。它不清楚当前工作区已经有半成品改动结果生成的代码跟现有改动冲突覆盖掉了我的辛苦成果。你告诉它先看 diff它就理解了当前是半成品会小心处理。“必须写测试”这条AI 默认是不会主动加测试的。它不觉得测试是你的需求的一部分你得明说。“禁止 print 调试”这个很好笑但很真实。AI 遇到 bug 的时候第一反应是往代码里塞 print 来调试跑完就忘了删。你写一条禁止它至少会收敛一点。3.6 禁忌与陷阱把历史踩过的坑钉死在这里这一节是 AGENTS.md 里性价比最高的部分。每一行都是一个历史事故的总结。我自己的项目里有这些条目## Pitfalls - 不要在 service 层直接使用 SQLAlchemy session必须走 repository - 禁止修改已发布的 API 响应字段名兼容性优先 - 删除或注释大量代码前先确认有无调用方 - settings.py 中未定义的新配置项不允许在代码中直接读取环境变量 - 缓存操作统一用 Redis禁止在进程内维护全局字典做缓存每一条都是血泪教训。以“禁止修改已发布 API 响应字段名”为例。有一次 AI 接手一个重构任务把响应里的userName改成了username。测试全绿前端全部挂掉。这种问题代码对吗对。这个改法合理吗从代码整洁度上讲也算。但就是不能做。这种项目特有的不变量你人不在 AGENTS.md 里写清楚AI 永远不可能知道。写这一节时有个技巧每条禁忌只写一行短促、明确、不解释。AI 对清晰的指令遵守度高对它还要推理的指令遵守度低。比如你不用写“不要直接查询数据库因为历史上有过几次事故导致数据不一致….”直接写“禁止在 service 中直接查询数据库”就够了。3.7 增量任务的原型模板对于频繁出现的任务类型写一个模板放在 AGENTS.md 里非常有用。比如这个项目经常要加新的数据上报接口那就可以写## Common Task Template: Adding a New API Endpoint 1. Define Pydantic schema in src/schemas/ 2. Write repository method in src/repository/ 3. Add business logic in src/service/ 4. Create route handler in src/api/ 5. Add test in tests/api/test_xxx.py 6. Run pytest tests/ -x -q to verify这个模板一写AI 处理这类任务时就不再自由发挥了整个流程是锁死的。而且如果你后续按这个流程做了模块化AI 生成的代码也能直接符合模块边界减少了重构需求。注意模板不用面面俱到只给任务最核心的运行框架。写太细反而会让 AI 在执行时过度思考。3.8 一个完整示例FastAPI 数据服务项目把上面的章节拼到一起我给你一个我实际项目里的精简版屏蔽了业务信息# AGENTS.md ## Project Overview 用户行为数据采集与分析服务。核心价值是稳定、可靠、低延迟。 任何改动都不应破坏已发布 API 的兼容性。 ## Tech Stack - Python 3.11 / FastAPI / SQLAlchemy 2.x / Alembic / Pydantic v2 - PostgreSQL 15 / Redis 7 - Ruff / Pytest / Docker Compose ## Project Structure - src/api/ 路由层参数解析与响应封装 - src/service/ 业务逻辑层禁止直接操作数据库 - src/repository/ 数据访问层所有数据库操作必须经过此层 - src/models/ ORM 模型 - src/schemas/ Pydantic 请求响应模型 - tests/ 测试目录镜像 src 结构 ## Commands - Dev server: uvicorn src.main:app --reload - Tests: pytest tests/ -x -q - Single test: pytest tests/api/test_user.py::test_create_user -x -q - Lint: ruff check src/ tests/ - Lint fix: ruff check --fix src/ tests/ - Migration upgrade: alembic upgrade head - Migration create: alembic revision --autogenerate -m desc ## Code Style - 类型注解必须完整所有函数参数和返回值都要标注 - 行宽 100由 Ruff 格式化不要手动换行 - import 按 标准库 → 第三方 → 项目内 分组中间空行 ## Workflow Rules - 开工前先跑 git status 和 git diff - 功能改动必须补测试 - 数据库结构变更必须生成 migration - 使用 structlog禁止 print 调试 ## Pitfalls - service 中禁止直接使用 SQLAlchemy session - 禁止修改已发布 API 的字段名或响应结构 - 禁止在代码中直接 os.getenv统一走 Settings - 缓存统一走 Redis禁止进程内全局字典缓存 - 大段删除前先查调用方 ## Task Template: Add New Endpoint schemas → repository → service → api → tests → pytest 验证这一份 60 行左右的文件已经能解决项目里 80% 的 AI 行为不规范问题。4. 不同场景下 AGENTS.md 的写法变体4.1 Monorepo 项目根目录写总纲子包写细节如果你的是一个多包仓库用单文件是扛不住复杂度的。根目录的 AGENTS.md 只写所有包共用的东西语言/工具版本全局命令如 monorepo 根的 Makefile 命令通用测试规范包管理工具的约束比如必须用 pnpm不能混用 npm然后在每个需要特殊约束的子包目录下写局部的 AGENTS.md# src/frontend/AGENTS.md 前端 Web 应用React 18 TypeScript。 - 状态管理用 Zustand禁止引入 Redux - 组件默认函数式不写 class component - UI 样式用 Tailwind禁止写内联 style - 新增页面必须在 routes.ts 中注册路由以这种粒度配置效果是最好的。因为 AI 在执行子目录任务时会优先读取近处的配置局部约束更精准。4.2 微服务架构项目按服务边界拆分微服务项目的 AGENTS.md 跟单体的差别在于每个服务都是一个独立的部署单元。根目录只需要放服务地图和跨服务的通信约定## Service Registry - order-service端口 8001订单核心流程 - payment-service端口 8002支付网关对接 - user-service端口 8003用户与鉴权 ## Cross-Service Rules - 服务间通信一律走 HTTP JSON禁止共享数据库表 - 跨服务调用失败必须重试并引入熔断不能直接报错 - 调用下游服务必须设置超时时间默认 3s每个服务目录再按前面的模板写自己那份。这样 AI 在处理某个服务时不会拿着另一个服务的命令来猜。4.3 算法/数据类项目加重数据流约束偏向数据处理的项目AGENTS.md 的重点应该放在数据流和资源边界上。这类项目遇到最多的问题是 AI 不懂数据的生命周期管理。比如一个推荐系统项目可以写## Data Pipeline Flow - 原始日志 → 清洗(daily job) → 特征表 → 模型输入 - 禁止在特征计算中读取原始日志表 - 所有特征表必须有 as_of_date 分区查询时强制带上 - 模型训练输出必须写入 model registry禁止本地 pickle 保存数据项目的禁忌往往比 Web 项目更致命AI 生成一个看起来能跑的数据处理脚本其实会全表扫几个亿的数据一执行就把任务队列打挂了。AGENTS.md 里写清“查询必须带分区条件”这种约束非常重要。4.4 纯前端项目聚焦工程化与约定前端项目的信息密度跟后端不太一样。重点要写的是组件写法的约定函数式、Hooks样式方案CSS Modules/Tailwind/styled-components选一种写死状态管理方案路由注册方式类型定义的放置位置文件命名规范前端项目很多规范本身就是“这样写不会报错、但项目里不是这么写的”。比如一个项目里组件目录是按业务划分的AI 看到已有的 button.tsx 就会把所有组件都往 components 里塞它没有意识到业务组件应该放 views 下。你在 AGENTS.md 里把目录语义写清楚减少很多搬来搬去的活。5. 实操中常见的问题与排查5.1 AI 不读 AGENTS.md 怎么办这是问得最多的一个问题。首先要排查是不是文件路径不对各大工具的识别路径有差异。我遇到过一个案例AI 工具只认根目录的 AGENTS.md子目录里的完全不读。这种情况你只能把子目录的核心约束合并到根文件里。其次是确认 AI 工具本身是否支持该功能。有些工具需要你在系统提示词里明确加入 AGENTS.md 的加载指令有些则自动读取。在上手一个工具前去它的文档里搜一下有没有 AGENTS.md 的说明没有的话可以手动在 system prompt 里附加一句“先读取仓库根目录的 AGENTS.md”。还有一种情况是文件内容太长工具做了截断。解决方法是精简把最核心的指令往文件前部放。AI 对文件开头的关注度比中后段高得多这个机制在很多模型里都存在。5.2 AGENTS.md 写得足够详细了AI 还是不遵守写得详细不等于写得有效。我见过好几个人把 AGENTS.md 写到上千行AI 依然我行我素。问题通常出在指令写得太模糊。“代码风格保持一致”不是一个可执行的指令AI 没有具体参考它就按自己的风格来。指令之间互相矛盾。比如既说“禁止修改现有逻辑”又说“重构这段代码”AI 会拿不准优先级。内容跟实际代码对不上。比如你写“禁止在 service 层使用 session 查询”但代码里有一堆旧的违规代码AI 会认为你在说废话。优先级的问题很实际。当多条规则冲突时AI 一般会怎么做看谁的指令更具体、更靠前。所以你要主动给规则排优先级## Rule Priority 1. 安全与兼容性绝不破坏已发布接口 2. 性能约束禁止全表扫 3. 代码风格最后满足这个优先级列表一出来AI 在做权衡时就有了准绳。5.3 命令列表过时导致 AI 瞎跑AGENTS.md 里的命令不是永久有效的。依赖升级、目录调整、工具链切换命令都会跟着变。AI 拿着过时命令跑失败它不会自己发现你写错了它只会觉得项目有问题然后开始“修正”。解决办法很笨但有效每半个月手动过一遍命令列表逐条跑一下。或者把命令列表单独放到一个 Makefile 或者 package.json 的 scripts 里AGENTS.md 只写“跑make dev”这种指向性指令具体命令以 Makefile 为准。这样你只需要更新一处AGENTS.md 不用动。5.4 团队协作时 AGENTS.md 的分歧处理团队成员对 AGENTS.md 的内容和近似程度有不同看法这是常态。有人希望 AGENTS.md 事无巨细有人希望它越短越好。我建议在项目早期就把这个文件当成评审对象不要在个人分支里囤了很久再合并。处理分歧的原则只有一个有用的留下没用的删掉。一个条目在这个仓库里有没有价值看的是“AI 要是没这条会不会犯错”。如果 AI 不犯错这条就是噪音删掉。另外建议团队里明确 AGENTS.md 的责任人一般由最熟悉项目全貌的人维护。不然就是一个没人管的文档逐渐腐烂。5.5 什么时候该把 AGENTS.md 拆分成多文件当你发现单个 AGENTS.md 文件越来越大、互相打架的规则越来越多就是拆分的时候。拆分有两种方向一是按目录拆。根目录写通用行为准则子目录写具体模块约束。二是按功能拆。比如把“如何运行和调试”单独拆成 RUNBOOK.md把“架构与设计约定”拆到 docs/architecture.md然后在 AGENTS.md 里用一句话指向它们“需要了解架构设计时阅读 docs/architecture.md”。第二种拆法要注意AI 不会主动去读你指向的文件除非任务内容恰好命中。所以拆完之后AGENTS.md 里的指令不能变成“去读那个文件”这种偷懒写法而是要在关键位置写入足够决策的核心信息把详细留档放在被指向的文件里。6. 一些更进阶的思路6.1 让 AGENTS.md 具备状态认知前面讲的文件都是偏静态的。再进一步你可以在 AGENTS.md 里记录项目的演化状态比如## Current Migration Status - 2025.06: order 表新增 refund_status 字段部分服务已切换 - 2025.07: 旧的 order_events 表计划下月废弃新代码禁止写入这种信息对 AI 的价值极大。因为 AI 以为它知道老表结构实际上它的训练数据里没有你上个月加的新字段。写明当前迁移状态能避免非常多“AI 用的 schema 和实际不一致”的荒谬错误。我一般会在每次结构迁移完成以后顺手更新这一节。这个习惯带来的收益是持续的——因为这个文件只要保持新鲜AI 的表现就一直在线。6.2 加入针对具体 AI 工具差异的引导不同的 AI 编码工具对 AGENTS.md 的处理方式有差异。有些工具优先读根目录的有些工具会同时读多个有些工具还支持 AGENTS.md 语法在对话中显式引用。我的建议是核心内容对工具中立放根目录。如果某个工具有独特的钩子机制利用它来显式触发文件加载而不是在文件里为特定工具做特化。6.3 AGENTS.md 与 CLAUDE.md 的关系顺带提一下 CLAUDE.md。Claude 官方生态里有个约定就是 CLAUDE.md 作为项目级指引文件很多项目已经在用了类似的东西还有 COPILOT.md、GEMINI.md 一类的。AGENTS.md 的出现其实是在收拢这个碎片化局面——它是跨工具的中立命名越来越多的工具开始认它。如果你已经在用 CLAUDE.md迁移到 AGENTS.md 的成本很低大部分内容直接搬过去就行。我自己的做法是在 AGENTS.md 里写中立的指令同时保留 CLAUDE.md 作为 Claude 专用行为附加说明比如 Claude Code 的权限配置、子代理怎么用。这种组合方式兼顾了通用性和特化需求。但别搞出五六个配置文件维护成本会失控。7. 最后说几句实在话我个人在实际维护过程中最大的体感是AGENTS.md 不是写一次就能一劳永逸的东西它需要持续打磨。每次 AI 犯错都是一次补充规则的机会每次你觉得这个文件没用大多不是文件没用而是文件已经烂掉了太久了。这个文件的价值跟写它的用心程度成正比——不是文采而是对项目细节的把控力。你有多少潜规则就能给 AI 立多少规矩。它越是精通你的项目你花在纠偏 AI 上的时间就越少AI 帮到你的地方就越多。如果你刚开始写我建议先别追求一蹴而就的完整版先搭一个 50 行的骨架放那让 AI 跑两周再根据实际的错误行为一条条添。这样长出来的 AGENTS.md 里面没有一条废话每一条都值钱。哦对了还有个小技巧把 AGENTS.md 的变更记录写在 git commit 里保持可追溯。这样你后来回头看某一条规则时你知道它是为什么加的——这比文件里写什么都有说服力。
返回列表