mcpField
C
code-standards

code-standards

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

关于 code-standards

Code Standards 是用于编写和审查代码及相关产物规范的技能,强调可读性、可维护的修复、测试质量,并提供按语言划分的参考指引。

主要功能

  1. 01可读代码结构指引
  2. 02可维护设计原则
  3. 03测试的最低要求
  4. 04注释与项目产物规范
  5. 05编写和审查工作流

适用场景

  1. 01编写代码时应用规范
  2. 02依据明确标准审查变更
  3. 03决定如何处理格式错误的输入
  4. 04处理规范与项目决策的冲突

安装

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

$npx skills add https://github.com/vivswan/skills --skill code-standards

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

包含的文件

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

LICENSE.md
README.md
.codex-plugin/
plugin.json
agents/
openai.yaml
references/
artifacts.md
comments.md
design.md
shape.md
structure.md
tests.md
references/languages/
go.md
python.md
rust.md
typescript.md
scripts/
python-order.mts

详细介绍

代码标准

代码及其相关产物的标准。编写时遵循这些标准,审查时检查这些标准。

可读性和美感优先。这里的每条标准都服务于它们;如果遵循某条标准反而会让内容更难读,就应让步。偏离标准时,用一句话说明,不要强行照搬。

这是银级标准,不是金级标准。语言和工具的演进速度快于本页更新:如果新版提供了更优美、更易读的写法,即使本页尚未跟上,也应采用新版写法,之后再更新本页。

下面每条标准都用几行说明规则,并附上确立该规则的示例(如有)。标准下方标注的 references/ 页面包含原因、应用方法清单和适用边界。处理标准的边缘情况前,先阅读该页面。

标准

修复问题根源,而非个别实例

系统性问题应从根源修复,使其不可能再次发生,而不是只修复眼前的个案。/never-twice skill 负责判断及其应对步骤。完整说明:references/design.md。

为通过底线的情况加上防护

凡通过 /never-twice 底线判断的问题,都应采用可实现的最高级别防护:用类型或结构让该状态不可能出现;否则,添加测试、故障触发器或流水线修复(如果无法触及流水线,则向用户提出建议);再否则,将规则记录为书面债务。完整说明:references/design.md。

通用设计优先于特例

将持续变化的维度设为参数,而不是硬编码当前实例;同一个概念只应有一条流水线。示例:某个安全分类器的规则手册不断变化,因此将其构建为分类器工厂,并把评估标准作为输入。完整说明(包括 DRY 原则的适用边界):references/design.md。

可维护性优先于投入

代码质量胜过 diff 大小和已投入的精力。大规模重构胜过错误的修复方式;不变量应由类型保证(/no-invalid-states skill),而类型无法保证的部分,则在边界处添加断言。示例:一个有文档说明的变通方案混合实现,最终被彻底重写,而非继续保留。完整说明:references/design.md。

优先使用库,而非自行实现

好的库已经能实现的功能,绝不自行实现;仓库中已有的工具也算在内:仅指声明的直接依赖或库自身的代码,不包括传递依赖、库的私有模块或 skill 的脚本。搜索须在写下第一行代码前完成,并记录在简报中,之后再记录于 PR 正文或合并报告中。大型库或适用性不明确时,应先向维护者确认。

示例:五个 CI 脚本所做的全部工作,已由一个已发布的软件包或 git diff --exit-code 实现。完整说明:references/design.md。

测试的最低标准

每个测试都必须达到的底线。测试应断言完整结果,并在名称或第一行中回答“如果没有这个测试,什么会悄然偏离预期?”——答案应是外部事实、跨文件一致性,或有名称的事故。常量或已发布文件是事实来源,绝不能用它们来验证自身。

应观察到防护测试在对应缺陷存在时失败。删除项本身没有行为时,应通过清点证明其正确性,而不是人为编造测试。测试固件应手工编写,绝不从真实数据记录而来。

示例:十五个分别断言字典中一个键的测试,合并为一个参数化测试,用于固定整个字典;测试函数从 81 个减少到 44 个,同时仍能捕获所有受防护的缺陷。完整说明和其他示例:references/tests.md。

注释只补充代码无法展示的内容

做出某个选择的原因、另一个文件所依赖的不变量、外部系统的特殊之处、此处看不到的后果、促使我们添加保护逻辑的输入。绝不解释代码的作用、类型、控制流、历史或其他选项。

先用一两句话说明,再仅在代码块更快时用对齐的行或箭头流程展示。绝不为了符合篇幅上限而硬塞文字:该删就删。写下或保留一条注释前,先问问:它说了哪些代码没有说的内容?一个疲惫的人能否一遍读懂?示例和 TODO 禁令:references/comments.md。

在边界处修复,否则就在边界处拒绝

格式错误的状态若只有一种明确的修复方式,就在边界处修复并报告;若无法修复或有多种修复方式,就在边界处拒绝。工具只读取的数据若格式错误,就拒绝;工具输出的数据则朝用户声明的目标修复;不让任何格式错误的数据流传出去,以免之后再失败。完整说明:references/design.md。

代码从上到下读起来都很优美

代码始终保持优美,一遍就能读懂。模块从上到下阅读,不需要滚回去查看;函数读起来就像步骤清单。本标题下的所有内容都只是默认规范,不是硬性规定:具体情况具体判断,偏离规范但读起来更好的做法应当采用;审查者若指出偏离,就应说明怎样写更易读。

  • **模块:**导入、所有常量集中在一个区块中(包括缓存)、类型,然后是函数。函数应放在调用它的代码之前,因此入口点是最后一个定义。若无法按此顺序排列,或这样会降低可读性,则以可读性为先,并说明偏离之处。区块分隔线只用于标记范围明确的小组:需要分区块的模块,就拆成两个模块。
  • **函数:**每个函数只表达一个概念,概念应能用几个词命名;概念越长,函数也可以越长。先写保护条件,每个单独成段,且不算作第二个概念;提前返回后,主体不再额外嵌套;用 continue 代替嵌套的循环。
  • **拆分,或合并:**两个能分别命名的事物应拆成命名步骤;若某一步只在一个地方调用,且本身不构成独立概念,就应合并回调用方。复杂度 lint 是兜底措施:要么说明原因后提高阈值,要么拆分;绝不在代码行内屏蔽,也绝不设得比语言页面规定的下限更严格。
  • **行:**避免难看的单行代码(嵌套条件、条件式拼接、首个匹配项查找、在条件中赋值、用 and/or 控制流程)。每行只做一次计算,并使用普通名词命名;三个值共用一种类型时,使用命名参数;清理逻辑应与资源获取绑定(with、defer、Drop、using)。
  • **主体:**设置之后、决策与分支之间、返回之前都空一行;if 及其唯一的执行语句之间不空行。
  • **表层:**每个签名都必须有类型标注;每个公共项都必须有文档注释,说明返回值和参数含义,绝不叙述其行为;除语言自身的可见性机制外,不得使用以下划线开头的模块级名称或属性名,除非该项是模块使用者绝不能触碰的内容(属性及其 setter 背后的值、框架固定的钩子)。

示例,确立段落规则的函数主体:

key = (video_key(video), audio_sig(video), model)

if key not in SEGMENTS:
    cache = cache_file(video, model)
    segments = read_cache(cache)

    if segments is None and window is not None:
        return with_min_words(transcribe_window(video, model, window), min_words)

    if segments is None:
        segments = run_asr(full_audio_wav(video), model, offset=audio_start(video))
        write_cache(cache, segments)

    SEGMENTS[key] = segments

segments = SEGMENTS[key]
if window is not None:
    segments = within_window(segments, window)

return with_min_words(segments, min_words)

规则及其示例:references/shape.md。各语言的 lint 下限和惯用写法,以及 Python 顺序检查器:references/languages/。

不要使用聚合文件或透传函数

删除仅用于导入的索引文件、“让旧导入方继续通过编译”的重新导出,以及整个函数体都只是转发到另一个函数的函数。将导入方或调用方改为直接指向定义所在的模块。包装器只有在确实增加了内容时才有存在的理由:默认值、转换、错误映射、注入的依赖或收窄后的类型。

令人困惑的布局是同一缺陷的更高层表现。可预测的布局会以每个文件的主要公开内容命名文件,并将辅助内容放在旁边;让文件夹中的同级文件遵循相同的内部模板;并在同级阶段中重复使用文件名,这样读者无需打开文件就知道某项内容的位置。不确定某项内容该放在哪里时,请向用户询问,并提供选项。

某个阶段的记录、常量和小型函数应分别集中在该阶段的 records、constants 和 util 模块中;如果一个包的内容适合放进一个模块,就将其合并为一个模块。以主要内容命名的模块可以只包含该内容;真正的缺陷是将某个调用方专用的辅助内容或常量单独放在这三个模块之外。

示例:一次整理将一棵目录树拆分成 269 个模块,其中一个文件只包含一个格式转换辅助函数,另一个文件只包含一个默认图层列表。

每个函数单独放一个文件,是同一缺陷的另一种表现:一个文件应包含一个概念及其辅助内容,正如一个函数应包含一个概念及其步骤。

任何文件都可以移动;纯移动应单独提交 PR,并附上导出清单和数量相同的测试。整个仓库的重组应先提出目标布局。完整详情:references/structure.md;各语言的聚合文件说明:references/languages/。

代码中不要引用规划文档

代码和注释绝不引用规划产物:工作包名称、尖峰或阶段标签、计划代号、审计问题编号。示例:以“WP-B spike, part 2:”开头的注释,脱离计划就毫无意义。完整详情:references/comments.md。

精简 AGENTS.md

AGENTS.md(以及 CLAUDE.md)只保留项目指导原则,以及 Agent 无法从其他地方推断的信息:项目是什么、负责人希望保留的约定、安全限制、工具链入口和参考链接。具体文件能够解答的问题,应删减为一行指引,且不应有测试固定其文本。示例:一个 66 行的结尾部分缩减为 15 行。完整详情:references/artifacts.md。

提交消息只写内容

按照仓库的主题约定,说明做了什么更改以及原因。不要注明 AI 或工具署名,不要对正文进行硬换行,也不要包含个人身份信息(遵循 /pr-and-issue-discipline 技能的规则)。唯一允许的署名是对社区中人的致谢。完整详情:references/artifacts.md。

Hook 只检查,不提交

提交前 Hook 检查开发者暂存的内容并给出报告:检查并失败,或检查、将修复写入工作树后仍然失败。绝不暂存、提交、格式化后重新暂存、运行会写入 Git 的命令、访问网络或安装任何内容。完整详情和示例:references/artifacts.md。

不要写大段文字

任何需要人类快速浏览的内容都应采用便于扫读的结构:每段 1 到 3 句;内容可枚举时,应使用列表。格式规则和段落检查工具见 /working-text 技能;PR 正文遵循 /pr-and-issue-discipline 技能。代码产物中的文字(如操作说明、CLI 帮助)遵循 /working-text 的页面规则。

工作流

  1. 编写代码: 边写边应用这些标准。在编写时遵循它们,比在审查时再处理成本更低。可读性和美观度优先:如果某项标准会让这里的代码读起来更差,就打破它,并用一行说明原因。
  2. 编写测试: 创建测试文件或添加测试用例之前,先将其漂移依据(外部事实、跨文件一致性或具名事件)写成名称或首行。没有依据,就不写测试。
  3. 审查: 对照审查标准进行检查,在每条发现中注明具体标准,并优先建议修正问题类别,而非修补单个实例。
  4. 边界: 如果某项标准需要明确边界(适用范围、豁免情况以及执行尺度),请先加载对应的 references/ 页面,再采取行动。
  5. 类型级修复: 如果某条发现要求在类型系统中强制执行不变量,请在重构本身中应用 /no-invalid-states 技能。
  6. 冲突: 如果某项标准与明确的用户或项目决策冲突,请遵循该决策,并记录有意搁置了哪项标准。

审查标准

  • 当问题通过 /never-twice 门槛的判断后,只修复当前实例:此更改能否防止问题再次发生(通过测试、类型或工具),还是只修补眼前的案例?
  • 对于已通过 /never-twice 门槛判断的问题,如果再次修复时没有采用可达到的最高层级:类型或结构修复、测试、熔断机制或流水线修复;如果无法触及流水线,则向用户提出建议;如果这些都不可行,则将书面规则记录为技术债。
  • 只断言形状、类型或某项内容存在的测试。
  • 手写的测试函数只在一个输入维度上有所不同,本应合并为一个参数化用例列表。
  • 从未在其防护的 bug 上失败过的防护测试。
  • 检查一个没有它也会明确报错的失败,或一个工具链会自行修复的失败;或者检查一个项目依赖的静默失败,却以「反正也会失败」为由不测试。
  • 新测试只是复述其读取的源内容(例如,工作流测试将 needs 固定为 yaml 中的列表、常量固定为其自身字面值、解析已发布的配置文件后再断言其原值);或者测试名称或首行没有说明没有它时什么内容会悄然漂移。
  • 为删除内容而编造、且自身不具备行为的测试,用来代替 PR 正文或合并报告中的盘点。
  • 从真实数据记录的夹具、说明其来源的注释,或用于测量真实数据且具有默认输出路径或仓库内输出路径的工具。
  • 特殊处理:新增一段与现有逻辑几乎相同的代码,而变化维度本应作为参数处理。
  • 为了缩小 diff 而增加复杂性:在有更清晰的重构方案或更强类型可用时,仍添加标志、嵌套结构或重复检查(/no-invalid-states 技能介绍类型层面的修复)。
  • 手写代码,无论是新增、移动、修改、复用还是作为依赖,其全部职责都已由优质库或仓库内现有工具承担;此类发现应指出具体库及其覆盖的职责。更改属于已有相关库的类别,但其记录(简述,随后是 PR 正文或合并报告)既未提及任何库,也未提及任何搜索过程。
  • 将技能脚本复制到仓库中,或在库相关发现中把传递依赖或库的私有模块算作仓库中已有内容。
  • 只是在描述代码本身的注释:代码做什么、其类型、控制流、历史或替代方案。
  • 读者无法一遍读完的注释:格式千篇一律(整段一段,或每条事实各占一行,且除两句说明外别无内容)、一句话包含多个想法,或为了符合长度上限而把文字压得过于密集。
  • 用整段注释解释变通方案(应标记底层代码,而不应只标记注释)。
  • 边界拒绝了工具能够输出并可明确修复的状态、修复了工具只读取的输入,或放过格式错误的输入任其稍后失败;或者修复步骤的注释是在争辩,而非说明规则。
  • 模块常量放在第一个函数之后、函数定义在其调用者之前、该拆分时却用章节分隔符、一个函数承载两个可命名概念、没有独立概念的单调用者步骤却从调用者中拆出、复杂度问题通过行内抑制而不是拆分或在配置层级说明原因,或 lint 上限严于语言页面规定的下限。
  • 嵌套条件表达式、条件拼接、可以一次性读取键控表却使用首次匹配查找、在条件中赋值、用 and/or 实现控制流、用 else 包裹守卫的主体、循环嵌套了本可用 continue 跳过的内容,或手写清理代码块,而该语言本可将清理与资源获取绑定。
  • 各决策之间没有空行的函数体、未标注类型的签名、缺少该语言规定形式的文档注释的公开项、超过三个简短段落的文档字符串,或叙述行为而非说明函数返回值的文档字符串;模块使用者可以触及的名称若以下划线开头(无论是模块级名称还是属性)。
  • 只转发到其他函数或模块的桶文件、重新导出垫片或转发函数。
  • 一个文件中包含两个主要内容、一个概念分散在多个文件中、文件名与其内容不符、将单调用者辅助项或常量放入自身模块而非 records、constants 和 util 模块、与同一文件夹中其他文件内部模板不同的同级文件,或同一概念在不同阶段的同级项中拼写不一致。
  • 移动内容后没有修复受影响路径(导入方、工作流或清单路径、注释、移动文件内的相对路径),在同一 PR 中除路径外还修改移动的代码,或缺少导出盘点和测试数量;因移动文件属于「无意义的折腾」而保留混乱布局。
  • 在代码或注释中引用规划材料(工作包、阶段、代号、发现编号)。
  • AGENTS.md 或 CLAUDE.md 包含可从代码或其他文档推导出的内容(目录树、强制检查清单、模块行为)、包含长段落,或有测试固定其文本内容。
  • 提交信息和 PR 描述中的署名行或强制换行的正文。
  • 执行检查并失败,或检查、写入修复并失败以外还会执行其他操作的 pre-commit 钩子:暂存、提交、写入型 git 命令、修复后通过、联网、安装或获取工具。 依据上述标准对发现的问题进行分级处理。每项标准对应一项发现。代码形状和布局标准属于默认规则:对此类问题的发现会指出怎样写更好;如果作者能用一句话说明偏离规则的理由,则可接受。

参考资料

跨语言标准,每项单独成页:

  • references/design.md:修正类别,守住底线,通用方案优于特殊情况(每个概念一条流水线,DRY 边界),可维护性优先于投入,优先使用库,在边界处修复
  • references/tests.md:测试的最低标准,漂移问题,证明防护有效的测试,删除内容的普查规则,手工编写的固定数据
  • references/comments.md:好注释应包含什么,先说明再展示,两个问题测试,示例,禁止 TODO,规划参考资料
  • references/shape.md:模块布局,先定义后使用,每个函数只处理一个概念,防护与提前退出,丑陋到清晰对照表,段落示例,类型与文档
  • references/structure.md:聚合导出,兼容性重新导出,辅助函数,迁移分阶段实施,可预测的布局及其示例目录树,纯移动 PR,以及重组的目标布局
  • references/artifacts.md:精简的 AGENTS.md,仅包含内容的提交消息及其两个例外,只检查、绝不提交的钩子

各语言中代码形状与聚合导出规则的具体应用方式,以及各自的 lint 基线和惯用写法:

  • references/languages/python.md:ruff 配置块,顺序检查器,__all__,with,Google 风格文档字符串
  • references/languages/typescript.md:biome 配置块,no-use-before-define,选项对象,using
  • references/languages/rust.md:clippy 阈值,let ... else,Drop 防护,mod.rs
  • references/languages/go.md:golangci-lint 配置块,defer,选项结构体,以包为单位

评论

支持 Markdown