关于 backend-code-review
backend-code-review 是用于审查 `src/backend/` 下后端代码的技能。它可检查待提交改动、粘贴的代码片段或指定文件,并覆盖安全、架构、数据库使用、测试和可观测性。
主要功能
- 01审查待提交改动、代码片段或文件
- 02安全与性能检查
- 03数据库和架构检查清单
- 04测试与可观测性审查
- 05提供带文件位置的可执行建议
适用场景
- 01提交前审查后端改动
- 02分析粘贴的 Python 代码片段
- 03检查指定的后端文件
- 04评估数据库访问、测试或日志记录
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ langflow-ai/ langflow --skill backend-code-review安装后在 Claude Code 中输入/backend-code-review确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/repositories-rule.mdsqlalchemy-rule.mdarchitecture-rule.mddb-schema-rule.md详细介绍
后端代码评审
何时使用此技能
当用户要求评审、分析或改进src/backend/ 目录下的后端代码(例如 .py)时,请使用此技能。支持以下评审模式:
- 待提交变更评审:当用户要求评审当前变更时,检查已暂存或工作区中计划提交的文件,以了解变更内容。
- 代码片段评审:当用户在聊天中粘贴代码片段(例如函数、类或模块的摘录)并要求评审时。
- 指定文件评审:当用户指出特定文件并要求评审这些文件时(一个文件或一小组明确指定的文件,例如
src/backend/base/langflow/api/v1/flows.py)。
以下情况请勿使用此技能:
- 请求涉及前端代码或 UI(例如
.tsx、.ts、.js、src/frontend/)。 - 用户并未要求评审、分析或改进后端代码。
- 范围不在
src/backend/下(除非用户明确要求评审src/backend/之外的后端相关变更)。
如何使用此技能
使用此技能时,请遵循以下步骤:
- 根据用户输入确定评审模式(待提交变更、代码片段或指定文件)。严格控制范围:只评审用户提供或明确提及的内容。
- 遵循检查清单中的规则进行评审。如果没有适用的检查清单规则,则将通用评审规则作为后备方案,尽力完成评审。
- 严格按照必需的输出格式撰写最终回复。
使用此技能时的注意事项:
- 始终提供可执行的修复方案或建议(可包含代码片段)。
- 在文件路径和行号可用时,尽量提供
文件:行号引用;否则,使用最具体的标识符。
检查清单
- 数据库架构设计:如果评审范围包含
src/backend/base/langflow/services/database/models/下的代码或文件,或src/backend/base/langflow/alembic/versions/下的 Alembic 迁移,请遵循 references/db-schema-rule.md 中的规则进行评审 - 架构:如果评审范围涉及路由、服务和模型分层、依赖方向或跨模块职责调整,请遵循 references/architecture-rule.md 中的规则进行评审
- 服务抽象:如果评审范围包含表或模型操作(例如
select(...)、session.execute(...)、联接、CRUD),且相关代码不在src/backend/base/langflow/services/下的服务中,请遵循 references/repositories-rule.md 中的规则进行评审 - SQLAlchemy 模式:如果评审范围涉及 SQLAlchemy/SQLModel 会话或查询的用法、数据库事务或 CRUD 的用法、
session_scope()的用法或原始 SQL 的用法,请遵循 references/sqlalchemy-rule.md 中的规则进行评审
通用评审规则
1. 安全审查
检查以下问题:
- SQL 注入漏洞(尤其是使用字符串插值的原始
text()查询)。后果:攻击者可以读取、修改或删除数据库中的任何数据。 - 组件 HTTP 调用中的服务端请求伪造(SSRF)。后果:攻击者利用服务器扫描内部网络或访问云元数据端点。
- 命令注入(尤其是在子进程或执行 shell 命令的组件中)。后果:攻击者获得服务器的 shell 访问权限。
- 不安全的反序列化(pickle、未使用 SafeLoader 的 yaml.load)。后果:在服务器上执行任意代码。
- 硬编码的密钥/凭据。后果:密钥会通过 git 历史记录泄露,且无法彻底撤销。
- 身份验证/授权不当(缺少
CurrentActiveUser依赖项)。后果:未通过身份验证的用户可以访问受保护的端点。 - 不安全的直接对象引用(查询缺少
user_id范围限定)。后果:用户 A 可以读取/修改用户 B 的流程、变量和 API 密钥。 - 文件存储操作中的路径遍历。后果:攻击者读取服务器上的任意文件(例如
/etc/passwd、.env)。
2. 性能审查
检查以下问题:
- N+1 查询(尤其是在循环中调用
session.execute())。后果:100 个流程会产生 101 次数据库查询,而非 2 次;页面加载时间会从 50ms 增至 5s。 - 经常查询的列缺少数据库索引。后果:大型数据集上会进行全表扫描;查询性能会从 O(log n) 降至 O(n)。
- 内存泄漏(无限增长的缓存、长期运行的服务中保留的引用)。后果:服务器运行数小时后发生 OOM;生产环境中的 Pod 会重启。
- 异步代码中的阻塞操作(
time.sleep()、同步 I/O、未使用run_in_executor的 CPU 密集型任务)。后果:整个事件循环停滞;所有并发请求都会挂起,直到阻塞调用完成。 - 未利用可缓存的昂贵计算。后果:每次请求都会重复计算相同结果。
- 未分页就将大型结果集全部加载到内存中。后果:当用户有 10K+ 个流程时,内存会激增,响应也会变慢。
3. 代码质量审查
检查以下问题:
- 代码是否能向前兼容 Python 3.10-3.13
- 代码重复(违反 DRY 原则——只有在 完全相同的业务规则 在 3 个或更多位置重复时才提取)
- 函数承担过多职责(违反 SRP 原则——如果需要用“以及”来描述函数职责,就应拆分)
- 嵌套过深/条件判断过于复杂(优先使用提前返回和守卫子句)
- 魔法数字/字符串(提取为有名称的常量或枚举)
- 命名不佳:缩写含义不明、名称具有误导性、名称过于通用(
data、result、obj、temp)。函数应使用动词(get、create、validate)。布尔值应使用前缀(is_、has_、can_、should_)。 - 缺少错误处理(裸
except、吞掉异常、静默失败) - 类型覆盖不完整(使用强类型;已知具体类型时避免使用
Any) - 使用 Python 3.10+ 联合类型语法(
X | Y而非Union[X, Y],X | None而非Optional[X]) - 对仅用于类型注解的导入使用
TYPE_CHECKING守卫(防止循环导入) - 在 FastAPI DI 中使用带项目别名(
CurrentActiveUser、DbSession、DbSessionReadOnly)的Annotated[Type, Depends(...)] - Google 风格的文档字符串(由 Ruff 强制执行):公开函数需包含
Args:、Returns:、Raises:部分 - 违反 SOLID 原则
- 违反 YAGNI 原则(在当前没有需求时为未来需求预先编写代码)
- 行长度超过 120 个字符(项目 Ruff 配置)
- 注释解释了“是什么”而非“为什么”(注释只应解释原因,不应复述代码)
- 注释掉的代码(应使用版本控制)
- 用于切换函数行为的布尔参数(应拆分为两个具有明确名称的函数)
- 存在不可变替代方案时仍使用可变共享状态(优先返回新对象,而非修改现有对象)
4. 文件结构审查
检查以下事项:
- 生产文件是否超过约 500 行代码(不包括导入、类型和文档字符串)。超过 600 行是危险信号,应按职责拆分。原因:超过 500 行的文件出现缺陷的概率在统计上更高,也需要更长时间审查。这表明文件承担了多项职责(违反 SRP)。在 Langflow 中,像
DatabaseService这样的服务如果超出此限制,应将其 CRUD 操作提取到专用模块中。 - 测试文件是否超过约 1000 行。超过时按逻辑分组拆分。
- 单个文件中承担不同职责的函数是否不超过 5 个(参见 AGENTS-example.md)。
- 每个文件是否只有一个存在理由和一个变更理由(SRP)。
- 是否存在通用文件名:独立使用的
utils.py、helpers.py、misc.py、common.py。原因:名为utils.py的文件会沦为无关函数的堆放处。几个月内,它就可能包含 50 多个涵盖格式化、验证、解析和 HTTP 调用的函数,从而违反 SRP。每组函数都应放在以其职责命名的文件中(formatting.py、validation.py)。
5. 测试审查
检查以下事项:
- 新代码路径是否缺少测试覆盖
- 测试是否没有验证行为(而是在测试实现细节)
- 测试是否存在不稳定模式(依赖时间、顺序或外部服务)
- 异步测试是否正确使用
pytest.mark.asyncio - 是否过度使用模拟(按照项目惯例优先使用真实集成)
- 覆盖率目标:80%(最低可接受值:75%)
- 测试反模式:说谎者(测试通过,却没有验证所声称的行为)、镜像(断言的内容与代码实际执行的内容完全一致)、巨型测试(设置代码超过 50 行)、模拟狂欢(只测试模拟设置)、实现检查员(与实现细节耦合)、链式帮派(依赖执行顺序)、不稳定测试(结果不一致)
Happy path 测试是基础,但远远不够。 测试还 MUST 挑战代码,以发现真实缺陷:
- 意外输入:
None、""、[]、{}、0、-1、UUID("00000000-0000-0000-0000-000000000000") - 边界值:最大长度字符串、恰好达到限制、超出限制一个单位、零个项目、最大项目数
- 格式错误的数据:缺少必填字段、多余的意外字段、类型错误、格式无效
- 错误状态:数据库宕机时会发生什么?外部 API 返回 500 时会发生什么?用户不存在时会发生什么?
- 不应发生的情况:验证用户 A 无法访问用户 B 的流程。验证已删除的流程会返回 404。验证无效的
endpoint_name会被以 422 拒绝。 - 错误消息和类型:不只是验证失败,还要验证是否以正确的异常和正确的消息失败
- 并发:两个请求同时尝试更新同一流程时会发生什么?
根据 REQUIREMENTS/SPEC 编写测试,而不是依据源代码当前的行为编写。 这样才能发现代码偏离预期行为时产生的错误。
测试失败时: 首先判断是否是代码有误,而不是测试有误。切勿在未弄清原因的情况下,默默修改失败的断言以匹配当前代码。
6. 可观测性审查
检查以下事项:
- 使用
lfx.log.logger中的异步日志记录器,并调用以a开头的方法(adebug、ainfo、awarning、aerror、aexception)。切勿使用print()或标准库的logging。 - 在关键决策点和边界处记录日志,不要在紧密循环内记录
- 包含:操作名称、相关 ID、结果(成功/失败),以及相关时长
- 使用正确的日志级别:ERROR(发生故障,需要处理)、WARN(性能下降但可恢复)、INFO(重要事件)、DEBUG(诊断信息,在生产环境中关闭)
- PII 容忍度为零:绝不记录电子邮件地址、用户名、电话号码、令牌或密码。仅允许使用以下标识符:
user_id、flow_id、session_id - 不要使用
print()语句——这些内容会进入生产日志 - 在日志消息中使用
{e!s}表示异常的字符串形式
7. 提交前验证
对于待处理更改的审查,请确认作者已运行:
make format_backend(Ruff 格式化工具)——格式不一致会产生大量噪声差异,掩盖代码审查中的实际更改。先格式化,再审查。make lint(MyPy 类型检查)——在 lint 阶段发现的类型错误,修复成本比生产环境中的运行时崩溃低 10 倍。Langflow 服务通过Service基类使用鸭子类型;MyPy 可尽早发现不匹配。make unit_tests(pytest)——测试失败意味着更改破坏了现有行为。切勿在测试失败时合并;请调查是代码还是测试有问题。
必需的输出格式
调用此技能时,回复必须严格遵循以下两个模板之一:
模板 A(存在任何发现)
# Code Review Summary
Found <X> critical issues need to be fixed:
## 🔴 Critical (Must Fix)
### 1. <brief description of the issue>
FilePath: <path> line <line>
<relevant code snippet or pointer>
#### Explanation
<detailed explanation and references of the issue>
#### Suggested Fix
1. <brief description of suggested fix>
2. <code example> (optional, omit if not applicable)
---
... (repeat for each critical issue) ...
Found <Y> suggestions for improvement:
## 🟡 Suggestions (Should Consider)
### 1. <brief description of the suggestion>
FilePath: <path> line <line>
<relevant code snippet or pointer>
#### Explanation
<detailed explanation and references of the suggestion>
#### Suggested Fix
1. <brief description of suggested fix>
2. <code example> (optional, omit if not applicable)
---
... (repeat for each suggestion) ...
Found <Z> optional nits:
## 🟢 Nits (Optional)
### 1. <brief description of the nit>
FilePath: <path> line <line>
<relevant code snippet or pointer>
#### Explanation
<explanation and references of the optional nit>
#### Suggested Fix
- <minor suggestions>
---
... (repeat for each nits) ...
## ✅ What's Good
- <Positive feedback on good patterns>
- 如果没有关键问题、建议、可选的小问题或值得肯定之处,请省略相应部分。
- 如果问题数量超过 10 个,请总结为“发现 10+ 个关键问题/建议/可选的小问题”,并且只输出前 10 项。
- 不要压缩各部分之间的空行;请保持原样以便阅读。
- 如果存在需要修改代码的问题,请在结构化输出后附上一句简短的后续问题,询问用户是否希望应用修复。例如:“您希望我使用建议的修复来解决这些问题吗?”
模板 B(没有问题)
## Code Review Summary
✅ No issues found.
评论
支持 Markdown