mcpField
D
dido-code-style

dido-code-style

github.com/didomarchet开发067 次安装1 天前更新
代码仓库

关于 dido-code-style

dido-code-style 是帮助 Dido Marchet 构建 Web 应用的编码规范技能,覆盖跨技术栈的实现与审查原则,并指向后端和 Nuxt 前端的专用技能。

主要功能

  1. 01跨语言编码原则
  2. 02项目上下文与连续性实践
  3. 03模块化和依赖规范
  4. 04可扩展性与副作用规则
  5. 05后端和 Nuxt 技能衔接

适用场景

  1. 01按项目规范实现代码变更
  2. 02审查代码变更并排查缺陷
  3. 03依据关联指南分析仓库或模块
  4. 04保持文档与代码变更一致

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/didomarchet/dido-skills --skill dido-code-style

安装后在 Claude Code 中输入/dido-code-style确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

analisi.md
repo-audit.js
riferimento/
skill-di-terzi.md

详细介绍

Dido 的代码风格与约定

你正在帮助 Dido Marchet 构建 Web 应用。请严格遵守这些约定:它们已在 Dido 的生产项目中验证,适用于所有技术栈。**处理相应代码时必须使用的技术栈技能:**后端使用 dido-backend,Nuxt 前端使用 dido-frontend-nuxt。

任务阅读内容
编写或修改代码第 1 部分,以及相应的技术栈技能
审查修改、“查找 bug”第 1 部分 + 第 2 部分“审查与 bug 排查”
分析仓库、模块或文件夹本文件旁边的 analisi.md

如果项目的 CLAUDE.md 有更具体的规定,则以它为准。


1. 适用于所有项目和语言的原则

上下文与延续性

编写代码绝不是凭空进行的:每项修改都以现有内容为基础,并让下一位参与者(无论是人还是 AI)了解发生了什么以及原因。

编写代码之前

  • 阅读项目的 CLAUDE.md、其中引用的文档和记忆:这里记录着决策、约束和已知限制。不要重新提出已记录为弃用或超出范围的内容(例如 docs/LIMITI-NOTI.md),也不要重新讨论已经做出的决定。
  • 了解你要修改的区域之前做过什么:git log --oneline -- <path>、近期提交、说明原因的注释,以及相关测试。先弄清代码为何如此编写,再进行修改。
  • 阅读涉及的完整流程,而不只是要修改的那一行:调用方、测试以及描述该流程的文档。编写新辅助函数前,先查找是否有现成的可复用函数。
  • 如果项目有基于同一 starter 衍生的姊妹项目,查看它们如何解决同一问题,并遵循相同约定。
  • 如果有不清楚之处或与文档矛盾的地方,请先询问:不要猜测,也不要悄悄推翻已有决定。

修改期间及之后

  • 对于不明显的决定,应在代码中添加说明原因的注释;如果它改变了项目的工作方式,还要在同一次修改中更新 CLAUDE.md / 文档,而不是事后补上。
  • 一项事实,只记录一处。 文档应记录代码本身无法表达的内容:决策及其原因、操作流程(包括所需命令和 URL)、各服务和模块的职责。其余内容应指向信息源:变量列在 .env.example 中,名称本身不足以说明含义的变量应在上方添加注释;端点则列在 OpenAPI 规范中。重复记录文件已有定义的表格、列表或图表,都是副本;而每个副本都会成为文档落后的地方。
  • 修改后,在仓库中搜索你改动涉及的关键词。如果文档重复记录了已修改的内容,应删除整份重复内容,而不只是改动的那一行,并改为指向信息源,而不是更新副本。修正文档中已不再适用的操作流程和决策。
  • 提交信息应使用项目所用语言说明改动内容及原因。
  • 代码和 git 未记录的事实(某项决策及其原因、约束、截止日期、外部参考资料)应写入记忆。
  • 最终报告应说明改动内容、已验证的事项以及尚待处理的问题,让下一步工作能够基于事实展开。

简单易读

  • 编写能解决今天需求的最简单代码。不是下一个需求,也不是假设中的需求。
  • 三行相似代码胜过过早抽象。只有在确实有重复调用点时才提取 helper,不要提前提取。
  • 一件事,一个组件。 如果某个部分几乎和已有的另一个部分做同样的事(滚动列表、下拉菜单、淡出效果、helper),就复用它:同一个组件、composable 或库。如有需要,只做最小扩展(一个 prop、一个 slot、一个 CSS 变量)。两个部分做同一件事,就已经是实际的重复调用点:绝不再复制一份,哪怕只有几条 CSS 规则。动手前,先在仓库里搜索已有的实现。
  • 不要使用只有一个实现或一个使用者的 factory、adapter、registry、基类、插件系统或配置选项。例外:已经具体规划了第二种实现,并且写在项目的 CLAUDE.md 中(例如,文件存储从 local 切换到 s3)。
  • 不要添加没人传入的参数、选项或标志。不要把特定函数泛化。
  • 一眼就能读懂:名称能说明事物是什么;用提前返回代替嵌套条件;每个函数只做一件事;不要写需要注释才能看懂的“巧妙”代码。

模块化,每个部分都可以移除

各部分协同工作,但每个部分都可以移除或关闭,其他部分仍能继续运行,只有真正依赖它的部分除外。写下隐藏依赖的那天看不出来,因为所有东西都还在。等有人移除某项功能或某个服务停止响应时,问题才会显现。

  • 与某项功能有关的所有内容都带上它的名称:它自己的文件夹,以及在技术栈按类型拆分的地方(组件、查询、语言、数据库 schema、API 规范、env 文件),也要有带此名称的文件、文件夹或区块。这样,移除功能的人就能找到所有相关部分,只需额外删除少数几行连接代码,例如路由挂载或布局中的 import。
  • 一个部分通过另一个部分的入口点(模块的 index、service、composable、prop)使用它,绝不直接访问其内部文件或状态。这样,查看 import 的 grep 就能看出谁在使用它,而其内部实现变更时无需改动任何使用者。
  • 可选部分依赖核心,而不是反过来。核心不 import 统计、错误跟踪或第三方 widget:这些部分通过框架机制(hook、事件、middleware、plugin、slot)接入。不是 API 客户端调用错误跟踪,而是错误跟踪监听错误。
  • 某个部分缺失、未配置或无响应时,只关闭依赖它的部分。无法缺少该部分的操作应自行失败,并给出清晰的错误。如果该部分只是辅助用途(日志、审计、统计、通知),操作仍应成功,问题则写入日志。这适用于确实可能缺失的内容,例如外部服务、配置和 CMS 数据。对于内部代码,仍遵循“一种问题,一种保护”。
  • 启动时只阻止缺少全局必需的配置,例如数据库和密钥。如果可选部分缺少配置,就让该部分保持关闭,并在日志中说明。
  • 模块化不意味着要增加抽象。按功能划分的名称和文件夹、入口点、单向依赖,以及框架已有的机制就足够了。不要自建插件系统、registry、事件总线或功能标志:遵循“简单易读”。
  • 在宣布完成之前,想想移除刚写的部分会导致什么损坏,并查找哪些地方 import 了它:结果应该只有它自己的接入点。对于可选部分或外部服务,也要尽可能尝试在没有它的情况下运行(不设置它的变量,或关闭服务)。其余部分必须能启动并正常运行。

为扩展而设计,而非过早扩展

数据量和流量增长时,代码依然能正常运行:这是设计,不是优化。

  • 可能增长的列表都要分页;查询只获取需要的字段;循环中不能逐项查询(N+1)。
  • 用于筛选、联接或排序的列都要有索引。
  • 不要使用在多于一个 worker 或容器时会出问题的进程内存状态——或者在项目文档中注明这一限制。
  • 大文件和大型数据集要使用流式处理;请求路径中不能有阻塞调用(*Sync、同步加密)。

“为流量增长后做准备”的基础设施属于过早设计:缓存、队列、worker、微服务、额外层级。只有在测量结果或实际事故表明有需要时才添加。添加缓存或优化时,要在上方写明原因的注释(测量了什么、可以接受多旧的数据):修改前先阅读。

不要有隐藏的副作用

  • 函数只做其名称所述的事,不做其他事:get、find、resolve、check、validate 不写入数据。
  • 不要修改参数或模块共享状态;返回新值。
  • 必须一起成功的写入要放在同一事务中。
  • 外部副作用(电子邮件、webhook、第三方调用、文件写入)要在数据保存后执行,绝不能放在可能回滚的事务中。

不要留死代码

  • 不要保留注释掉的代码、未使用的函数 / export / import / 变量 / 依赖项 / 配置键 / 文件。历史由 git 保存。env 文件及其变量不在此列:参见“env 文件”。
  • 不要为已不存在的情况保留回退路径。不要为无人计划处理的工作添加 TODO。

更改内容时,删除旧内容

  • 用 Y 替换 X → 在同一次修改中删除 X:代码、测试、文档、API 规范、配置。env 文件除外:参见“env 文件”。
  • 除非 Dido 要求,否则不要添加向后兼容垫片:不要保留已弃用的别名、旧名称的 re-export、改名为 _unused 的变量、// removed X 标记,也不要同时读取新旧字段。
  • 在说“已从所有位置删除”之前:使用带单词边界的 grep(grep -rn '\bnome\b' src/ tests/ docs/),不要使用过于狭窄的模式。残留内容常藏在测试和查询 / 筛选中。

env 文件

  • 每个 repo 的根目录都有三个 env 文件,全部纳入 repo:.env.example、.env.local(开发环境)和 .env.production。不要在 git 之外保留其他 env 文件。
  • 文件中包含真实值,包括机密,因为这些 repo 是私有的。仅当值需要生成或从其他位置获取时,才使用 CHANGE_ME。
  • 不要删除或合并这些文件,即使其中两个内容相同也不行。除非 Dido 要求,否则不要删除任何变量或值、将其清空或改成占位符,即使代码已不再读取它们也不行。
  • 新变量必须添加到这三个文件中,名称相同。

一个问题只用一种防护机制

  • 如果某个 bug 或风险已由现有机制覆盖,就不要再添加第二种机制“以防万一”。针对不同故障情况保存多份数据(设备丢失、服务器从备份恢复、用户操作错误)不算重复:每份数据各自应对一种问题。
  • 不要处理不可能发生的错误情况:已有会抛出异常的守卫后,不要再做 null 检查;不会抛出异常的代码不要用 try/catch 包起来;已在上游验证的数据不要重复验证。“不可能”意味着代码已将其排除,例如前面不久就有守卫,而不是“从未遇到过”。
  • 在边界处验证,然后信任内部代码。边界是代码无法控制的一切:用户输入、外部 API、启动时的环境变量,以及浏览器中的本地存储(配额已满、数据被浏览器删除、连接已关闭)、网络、其他标签页、页面关闭或被系统挂起。在这些地方,错误绝不可能算作“不可能”。

最小改动

  • 修复只改出问题的行,不改模块。“顺便重构”应单独提交,且只有 Dido 要求时才做。
  • 不要重新格式化、重命名或调整未要求修改的代码顺序。
  • 与周边代码保持一致:命名、惯用写法、文件结构、语言和注释密度。
  • 现有代码不是规则。若它与这些技能相悖(重复代码、重复组件,或使用了与此处所述不同的方法),应以这些技能和 Dido 的指示为准,即使那段代码是别人写的。按它们的要求处理,并在报告中写明差异。

注释

  • 说明为什么,而不是说明做了什么。
  • 对于已有的不明显选择,应添加注释说明原因(例如:// 不缓存:...)。
  • 对于有人可能会“修正”的刻意缺失,应简短注释说明原因(例如:不缓存 SMTP 客户端,因为服务端会运行于多个进程)。这不是 // removed X 这样的标记,而是解释设计决策,不是记录历史。

文案

所有供人阅读的文本(界面、邮件、错误消息、注释、文档、报告),都应在读者需要采取行动时提供。句子要简短,用读者熟悉的词语。编写新文案前,先查看已有文案(模板、语言文件、邮件),并沿用相同的语体和称呼方式。

在界面中,页面、区块或卡片应包含标题、内容和操作。只有在以下三种情况下才添加副标题、说明和帮助文本:

  • 字段要求特定格式或有不明显的限制(“最大 10 MB”);
  • 操作无法撤销,此时应在确认对话框中说明,而不是放在页面上(“删除账户?订单和地址无法恢复。”);
  • 出现问题时,消息应说明问题和补救方法(“文件超过 10 MB。请选择更小的文件。”)。

按钮应写明操作(“保存”“发布”),标签应写明对象名称。

使用常规标点:句号、逗号、冒号、括号和直引号("…"),不要使用书名号(« »)。在界面中,句子里提到的按钮、状态或字段名称应使用粗体;在没有格式的文本中(提示条、提示、错误消息),则应使用直引号。每段最多使用一个长破折号(—)和一个间隔号(·);术语与其解释之间使用冒号。

测试

  • 每个新行为和每个错误修复都要有测试,且没有该改动时测试应失败。修复错误时,先编写测试并确认其失败。
  • 从公共接口测试行为(HTTP 路由、渲染后的组件、CLI 输出),不要测试内部实现。
  • 不要为了让测试通过而修改测试。如果行为变更是有意的,应在改动中说明。
  • 如果项目没有测试配置,应在报告中说明;未经要求,不要添加测试框架。

安全贯穿每次修改

每次修改在被视为完成之前,都必须经过与影响范围相称的安全检查:CSS 微调不需要全面检查,新增端点则需要全面检查。

  • 输入。 每个外部输入(请求体、查询参数、路径参数、标头、Cookie、上传文件、Webhook、第三方 API 响应)都必须在边界处验证:类型、格式、长度、允许的值。
  • 身份验证与授权。 谁可以调用它?检查必须在服务器端进行,绝不能只是在 UI 中隐藏。用户能否通过更改 ID 访问他人的数据?已停用或降级的账户是否会立即失去访问权限?
  • 数据暴露。 响应只返回必需字段:生产环境绝不返回密码哈希、令牌、OTP、机密、堆栈跟踪或驱动程序错误。日志中绝不包含密码、令牌或 OTP。
  • 注入。 不得通过拼接字符串来构造 SQL、Shell 命令或 HTML:使用参数化查询 / ORM、自动转义的模板,且不得对用户可控的内容使用 v-html / innerHTML。
  • 机密。 放在仓库的 env 文件中(见“Env 文件”),或以静态加密方式存储;绝不能放在代码、日志或客户端 bundle 中(客户端 bundle 中只能放置本质上公开的值,例如只读 CMS 令牌)。
  • 滥用。 对所有可能被恶意触发或用于发送垃圾信息的功能实施速率限制(登录、OTP、密码重置、注册、上传、联系表单)。还要检查每项保护措施(计数器、封锁、限制)是否可能被他人触发:如果陌生人能让其他人的账户触发保护措施,就会导致账户锁定。令牌必须随机生成、有有效期且只能使用一次。登录和密码重置响应不得透露账户是否存在。
  • 文件。 检查类型和大小,使用生成的名称保存,不得使用用户可控的路径,私有内容只能在身份验证后下载。
  • 传输与浏览器。 明确设置 CORS 允许列表,Cookie 使用 HttpOnly + Secure + 正确的 SameSite,生产环境使用 HTTPS。
  • 依赖项。 新增依赖项必须确实有用(不能用几行代码替代)、有人维护,且不存在已知的严重漏洞(npm audit / pnpm audit)。

然后:

  • 添加保护措施之前,先检查现有措施是否已覆盖相关风险(项目的 CLAUDE.md、代码注释):“一个问题对应一项保护措施”这一原则同样适用于安全。
  • 由你的修改引入的漏洞必须在同一次修改中修复。超出此次修改范围的既有漏洞,应说明具体场景和严重程度:不能默不作声,也不能通过未经要求的重构来“修复”。
  • 最终报告中必须有一行说明安全检查的情况:检查了什么,以及发现了什么(或“未发现问题”)。

只有验证过才算完成

  • 未实际运行之前,绝不要说“完成”或“有效”:需运行测试、仅做检查的 lint 和格式化、构建、实际命令、实际端点。“编译通过”不代表“有效”。
  • 修改架构或生成的代码后,先重新生成,再运行任何操作(例如 npx prisma generate)。
  • 明确说明已验证和未验证的内容,以及原因(例如:“数据库未启动,未运行测试:以下是运行方法”)。

警示信号:停下来,先修正再继续

想法现实
“为了兼容,我保留旧函数 / 字段 / 变量”没人要求这样做。在这次修改中将其删除,并更新测试和文档。
“这个 env 文件是重复的 / 没人读取这个环境变量,我把它删了”env 文件应保持 Dido 创建时的样子,保留所有值。只有 Dido 要求时才修改。
“我把它做成可配置 / 通用的,或许以后会用到”只有一个使用者 = 不需要抽象。编写专用版本。
“我需要的功能和 X 差不多,就在这里重写一份”使用 X,并通过 prop 或 slot 扩展它。第二份副本就是一个潜伏的 bug。
“旁边的代码就是这么做的,它已经有自己的副本了”现有代码不是规则:应遵循 skill,并指出差异。
“我直接导入内部文件,省点事”通过它的入口导入,否则下次修改那部分时就会破坏你的代码。
“我在这里调用统计 / 错误跟踪”这是挂接到核心的可选部分,应使用 hook 或事件。
“没有这个变量,应用就无法启动,这样他们就会注意到”如果只有某个部分需要它,就只关闭那部分,并在日志中说明。
“我加个缓存 / 队列,以防万一”没有衡量就不加缓存。
“我再加一道检查,有备无患”找出已有的覆盖方式:一个问题只保留一个防护措施。
“既然我已经在这里了,顺便把这个也修一下”单独修改,而且只有 Dido 要求时才做。
“这个看起来不对,我改了”先阅读注释、git log 和文档:这可能是有意为之的决定。
“能编译,所以就算完成了”实际运行,并报告运行了什么。
“文档以后再更新”在同一次修改中更新,否则永远不会更新。
“我也更新 README 中的表格”如果表格重复了代码,就删除并改为链接到权威来源。

2. 审查与分析

审查与查找 bug

审查修改,或处理“查找 bug”之类的请求时:

  • 假定代码可以正常工作:举证责任在于指出问题的一方。
  • 只报告严重程度为高或中等的问题(见下文“严重程度”)。未发现问题 → 用一行回复“正常”。
  • 不要报告美观、命名、微小简化、理论上的竞态或面向未来的改进,除非 Dido 要求。结尾绝不要加上“另外还注意到一两个小问题”。

严重程度

严重程度问题
高数据丢失或损坏、安全漏洞、用户可见的错误、会话或凭据丢失、账号锁定
中等文档所述场景下状态不一致、重试或幂等性失效、实际瓶颈、测试失败、误导客户端的 API 文档、某个可选部分或外部服务缺失或无响应时,导致不依赖它的部分也一起崩溃
低过度设计、死代码和残留项、能带来具体收益的简化、其他不一致的文档、文档中的重复内容、关键流程缺少测试、文本、其他模块化问题(导入内部文件、核心导入可选部分、某项功能的代码分散在多处)

完整分析(“分析代码仓库”)

分析代码仓库、模块或文件夹时,请阅读本文件旁边的 analisi.md:其中说明了运行 repo-audit.js 工作流的成本和方式、它会检查什么、什么情况下问题会被证伪,以及报告的格式。

评论

支持 Markdown