关于 sliced-bread-review
用于按 Sliced Bread 架构原则审查代码变更的技能。它检查依赖方向、切片边界、领域模型纯度、抽象增长依据和事件使用,只报告问题而不修改代码。
主要功能
- 01检查变更文件的依赖方向
- 02检测绕过切片公开接口的导入
- 03审查领域模型的基础设施依赖
- 04评估新增抽象是否有实际压力
- 05检查事件是否用于反向依赖
适用场景
- 01审查分支或未提交变更
- 02定位跨层依赖与切片边界违规
- 03在合并前发现不必要抽象和事件用法
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ paulnsorensen/ sliced-bread-architecture --skill sliced-bread-review安装后在 Claude Code 中输入/sliced-bread-review确认已加载。
详细介绍
Sliced Bread Review
根据 Sliced Bread 架构审查目标变更集。完整的设计依据请参阅 https://cheeselord.dev/sliced-bread-architecture/reference/sliced-bread/; 本技能是一份操作检查清单。
范围
按以下优先级,根据调用确定审查目标:
- 用户指定的路径、差异、分支或 PR。
- 当前分支与默认分支之间的差异。
- 未提交的更改(
git diff HEAD)。
只审查已更改的文件,以及已更改的导入所指向的文件。
五项检查
对每个已更改的文件执行所有检查。每项发现都要注明 file:line,并引用违规的导入或定义。
1. 导入方向
箭头只能指向允许的方向。只有组合根(app/bootstrap、main)可以导入具体适配器,且任何内容都不能导入 entrypoints/。一个切片可以直接导入相邻切片的公共接口。
箭头描述的是允许的方向,而非必需的目录结构——仓库没有 entrypoints/ 层并不违规。
entrypoints/ -> app/ -> domains/* -> domains/common/
app/bootstrap -> adapters/ (composition root only)
adapters/ -> domains/* (implement domain ports)
Never:
app/use_cases/* -> adapters/*
domains/* -> adapters/ | app/ | entrypoints/
adapters/* -> app/ | entrypoints/
common/ -> sibling domains
anything -> entrypoints/
任何违反这些箭头方向的情况都是阻断级问题;用例导入具体适配器则为中级问题。
2. 外壳完整性
外部使用者应以语言原生形式使用切片的公共接口——Go 中的导出标识符、Python 中的包 __init__ 接口、TypeScript 中的 index 模块,或其他语言中的公共类接口——不得使用其内部实现。from domains.pricing import calculate_discount 没问题;
from domains.pricing.discount_calculator import ... 则违规——有多个使用者时为高级问题,只有一个使用者时为低级问题。
3. 模型纯粹性
领域文件只能导入标准库、common/ 和相邻切片的公共 API。领域文件导入 HTTP 客户端、ORM 或队列即为违规;修复方法是在领域中定义一个端口(协议),并由适配器实现。
严重程度根据下文严重程度中的 doctrine:severity-cases 矩阵,按首次匹配的情况判定。
4. 增长依据
新增目录和抽象必须有明确的压力作为依据。两个具体用途是通常的证据门槛,但不是硬性要求。抽象基类只有一个实现、尚无事件时就引入事件总线接口,或只有一个插件的注册表,若没有具体压力作为依据,则属于中等问题。以下检查中的“数值阈值”指建议性的增长信号(约 200 行、3 个以上概念、3 个以上聚集的文件),而非可评分的限制。请排除以下误报:
- 只有一个使用方本身并不能证明抽象过早;应评估是否存在具体压力。两个使用方是通常的证据,但不是硬性要求。
- 新概念若始终只有一个文件且确实只使用一个文件,这是正确做法;不要标记。
- 为打破跨切片循环依赖而引入的调度器,是明确存在压力的体现,即使只有一个事件和一个订阅方。
- 数值阈值是建议性信号,不是可评分的违规项;应评估实现占比、公共接口规模和生命周期混杂情况。
- 如果某种语言唯一的隐私机制是文件位置,那么用于标记其内容为内部内容的子目录,就是该可见性边界存在明确压力的体现,即使其中只有一个文件。
| ID | 条件 | 预期结果 | 理由 |
|---|---|---|---|
growth-cycle-event | 引入事件调度器以打破跨切片循环依赖。 | allow | 调度器消除了具体的循环依赖,是“以压力为先”的增长信号的典型例外。 |
growth-positional-one-file | 在没有其他隐私机制的语言中,单文件位置层用于标记内部可见性。 | allow | 该目录是可见性边界,而非推测性的增长结构,即使其中只有一个文件也是如此。 |
growth-single-unpressured | 一个新抽象只有一个具体使用方,且没有明确的压力作为依据。 | medium | 尚未达到通常的两个具体使用方这一信号,因此应将该抽象视为可能过早并提出质疑,而非视为阻断性问题。 |
请按首次匹配顺序应用由参考资料维护的 doctrine:growth-cases 矩阵;不要根据矩阵外的说明推断结果。
5. 事件使用
事件用于处理反向依赖:B 对 A 作出响应,而 A 无需了解 B。
切片之间的循环依赖必须通过定义在 common/ 中的事件解决,而不能相互
导入(high)。
若将事件用作通用消息机制,而直接导入才是自然的依赖方式,则属于中等问题。
严重程度
上述检查中引用的严重程度来自此表。
| 严重程度 | 含义 |
|---|---|
| blocker | 依赖箭头反向;领域文件在导入时执行基础设施操作 |
| high | 跨切片内部导入;切片依赖循环;多个使用方绕过 crust |
| medium | 模型纯粹性偏移(导入了基础设施,但未在导入时执行);过早抽象;将事件用作消息传递;在组合根之外导入适配器 |
| low | 单个使用方绕过 crust;命名偏移 |
| ID | 给定条件 | 预期结果 | 理由 |
|---|---|---|---|
severity-import-exec | 领域模块在导入时执行基础设施操作。 | blocker | 导入时副作用会让每个使用方都承担基础设施开销,并可能在应用启动受控之前就导致失败。 |
severity-static-domain-infra | 领域模型对基础设施存在静态依赖。 | medium | 该依赖违反模型纯粹性,并增加变更耦合,但单独的静态依赖边本身并不构成导入时执行失败。 |
severity-static-concrete-adapter | 用例或应用服务导入了具体适配器,而不是领域端口。 | medium | 应用层与基础设施的选择相耦合;通过端口进行依赖注入可恢复预期的边界。 |
severity-other-forbidden-edge | 依赖边指向禁止的方向,且不符合更具体的严重程度情形。 | blocker | 未匹配的结构性反转会破坏切片依赖约定,必须立即修正。 |
按首次匹配顺序应用由参考规范维护的 doctrine:severity-cases 矩阵;不要根据矩阵之外的说明推断结果。
输出
按严重程度分组报告发现项,最严重的排在前面。每项发现:
严重程度 — 检查项 — 文件:行号 — 引用的证据 — 一行修复建议。空报告也是有效结果;绝不要捏造发现项。不要修复任何内容——此技能仅用于审查。