关于 clojure-review
面向 Metabase 贡献者的 Clojure 代码审查技能,会依据项目规范及工作目录中存在的社区风格指南检查差异,并聚焦于违规项和潜在问题。
主要功能
- 01检查 Metabase Clojure 规范
- 02存在时检查社区风格指南
- 03审查命名、文档、组织和测试
- 04排除表扬及由 Linter 检出的括号问题
适用场景
- 01审查 Clojure 代码更改
- 02检查公开变量和文档字符串
- 03查找 API、数据库或模块规范问题
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ metabase/ metabase --skill clojure-review安装后在 Claude Code 中输入/clojure-review确认已加载。
详细介绍
Clojure 代码审查 Skill
@./../_shared/clojure-style-guide.md @./../_shared/clojure-commands.md
审查指南
需要标记的内容:
- 检查是否符合 Metabase Clojure 风格指南(已包含在上方)
- 如果工作目录中存在
CLOJURE_STYLE_GUIDE.adoc,还要检查是否符合社区 Clojure 风格指南 - 标记所有风格指南违规
不要发布的内容:
- 不要发布祝贺他人做出琐碎改动或遵循风格指南的评论
- 不要发布确认内容“看起来不错”或告诉他人做得正确的评论
- 只发布关于风格违规或潜在问题的评论
应避免的错误代码审查评论示例:
这个 TODO 注释的格式正确,包含作者和日期——做得好!
给查询加上 limit 1 是个不错的补充——这让测试更高效,同时不改变其行为。
kondo ignore 注释放在这里是合适的
测试名称按风格指南要求正确地以 -test 结尾。
特殊情况:
- 不要发布关于缺少括号的评论(这些会被 linter 捕获)
快速审查清单
使用此清单高效地浏览改动:
命名
- 描述性的名称(不要用
tbl、zs') - 纯函数以描述其返回值的名词命名
- 所有变量和函数使用
kebab-case - 有副作用的函数以
!结尾 - 函数名中不重复命名空间别名
文档
-
src或enterprise/backend/src中的公开 var 有有用的 docstring - Docstring 使用 Markdown 约定
- 引用使用
[[other-var]]而非反引号 -
TODO注释包含作者和日期:;; TODO (Name 2025-01-01) -- description
Docstring 内容——对照上方风格指南中的反模式表,检查每一个新增或重写的 docstring。单独阅读 diff 中的 docstring,与代码分开来看:散文正是审查注意力容易溜走的地方,而冗长的 docstring 读起来像是在尽责, 实际上却往往是一种负担。
代码组织
- 除非在其他地方使用,否则一切都要
^:private - 尽可能避免
declare(公开函数放在末尾) - 函数尽可能在 20 行以内
- 定义形式内没有空白非注释行(
let/cond中的成对构造除外) - 行长度 ≤ 120 个字符
测试
- 不同的测试用例使用独立的
deftest形式 - 纯测试标记为
^:parallel - 测试名称以
-test或-test-<number>结尾
模块
- 正确的模块模式(OSS:
metabase.<module>.*,EE:metabase-enterprise.<module>.*) - API 端点位于
<module>.api命名空间 - 公开 API 使用 Potemkin 位于
<module>.core - 不要用
:clj-kondo/ignore [:metabase/modules]欺骗模块 linter
REST API
- 存在响应 schema(
:- <schema>) - 查询参数使用 kebab-case,请求体使用
snake_case - 路由使用单数名词(例如
/api/dashboard/:id) -
GET没有副作用(analytics 除外) - Malli schema 详细且完整
- 所有新端点都有测试
MBQL
- 不在
lib、lib-be或query-processor模块之外直接操作原始 MBQL - 使用 Lib 和 MBQL 5,而非旧版 MBQL
数据库
- 模型和表名使用单数名词
- 只取一列时使用
t2/select-one-fn,而非选取整行 - 逻辑放在 Toucan 方法中,而非辅助函数中
驱动
- 新的 multimethod 记录在
docs/developers-guide/driver-changelog.md中 - 将
driver参数传递给其他驱动方法(不要硬编码驱动名称) -
read-column-thunk中的逻辑尽量精简
其他
- 示例数据尽可能以鸟类为主题
- Kondo linter 抑制使用正确的格式(不要用
#_:clj-kondo/ignore关键字形式)
模式匹配表
快速排查常见问题:
| 模式 | 问题 |
|---|---|
calculate-age、get-user | 纯函数应使用名词:age、user |
update-db、save-model | 副作用函数缺少 !:update-db!、save-model! |
snake_case_var | 应使用 kebab-case |
| 公共变量没有文档字符串 | 添加文档字符串说明用途 |
;; TODO fix this | 缺少作者/日期:;; TODO (Name 2025-01-01) -- description |
在其他命名空间使用的 (defn foo ...) | 应为 (defn ^:private foo ...) |
| 函数超过 20 行 | 考虑拆分为更小的函数 |
/api/dashboards/:id | 使用单数形式:/api/dashboard/:id |
查询参数使用 snake_case | 查询参数应使用 kebab-case |
| 新增 API 端点但没有测试 | 为该端点添加测试 |
反馈格式示例
针对风格违规:
这个纯函数应以描述其返回值名词命名。考虑使用
user代替get-user。
针对缺少文档:
这个公共变量需要一个文档字符串,说明其用途、输入和输出。
针对文档字符串描述了不属于它的代码:
这里描述了
lib在内部如何决定分箱策略。当这一点发生变化时,这里不会有任何东西失败, 因此它会悄无声息地过时——删掉它,让available-binning-strategies为自己的行为 作答。
针对文档字符串内容应放在函数体中:
这一段解释了分支为何按此顺序排列,这正是编辑
cond的人需要了解的内容—— 但调用方无法据此采取行动。把它移到cond上方的行内注释中。
针对组织问题:
这个函数只在此命名空间中使用,因此应标记为
^:private。
针对 API 约定:
查询参数应使用 kebab-case。将
user_id改为user-id。