abadcafe/superteam/module-design

Claude Code and agent skill by abadcafe/superteam

Trust tier 2
  • community
LLM review pending
Source check pending

Checking that the SKILL.md file is still in the repository.

Use whenever writing code, writing tests, designing architecture or modules, refactoring, or reviewing code, to enforce module boundaries, public interfaces, dependency direction, cohesion, coupling, information hiding, and black-box tests that use only public interfaces.

Install

npx vskill@latest install abadcafe/superteam/module-design

SKILL.md

Module Design

设计各个模块时, 必须遵循以下规范. 这些规范源自经过实证的软件工程原则, 不可违反.

注意, 例如bindgen, grpc等工具自动生成的模块, 保持其原样, 不受规范约束.

1. 模块定义

以 Rust 为例:

  • 一个 xxx.rs 文件是一个模块. 模块下面还可以有子模块, 即 xxx.rs + xxx/ 目录,

xxx/ 目录下是 xxx 的子模块(子模块也是模块)

  • 单独一个函数、一个子程序、一个例程、或者一个类(struct/trait/enum), 都不是模块
  • Crate 不是模块, 它是多个模块的集合
  • Python 的包和模块都是模块,等于 Rust 的模块和子模块

模块是类之上的更大组织粒度——一个模块内含多个相互关联的函数、struct、trait、enum 等项, 是对相关功能的聚合容器.

1.1 模块设计

模块的行为由测试用例定义. 每个模块必须声明模块名、职责、公开操作、主要数据实体和测试用例:

module: auth
responsibilities: user authentication and token management
public operations: login, logout, refresh_token, validate_token
data entities: User, Token, Session
tests: test_login_success, test_login_invalid_password, test_logout, test_token_refresh, test_token_expiry

2. 模块约束(不能怎样)

2.1 大小约束

枚举三个维度, 任一超阈值则必须拆分:

维度含义阈值
职责用一句话能说清的独立职责, 需用"和/与"连接即为多个>3
公开操作模块对外暴露的 pub 项(fn, struct, enum, trait, type, const 等)>14
数据实体模块内定义的 struct/enum/type>7
测试用例模块对应的测试用例总数>35
2.2 内聚约束
  • 禁止巧合内聚: 不得创建 utils、misc、helpers、common 等以"杂项"为名

的模块——这种模块内部操作之间没有任何可辨识的关系, 是最差的内聚形式

  • 禁止逻辑内聚: 不得在模块中通过控制标志(flag/enum 参数)选择执行不同的操作——

不同操作应拆为独立模块

  • 禁止将无关项混入同一模块: 如果模块中半数函数操作半数数据, 另外半数函数操作

另外半数数据, 则实际上有两个模块伪装成一个, 必须拆分

2.3 耦合约束
  • 禁止循环依赖: 模块间的 use 依赖不得形成环路. 环路使所有被圈入的模块变成

一个"超级模块", 任何一个发布都必须构建全部. 打破环路的方法:

  1. 提取共同依赖到新模块
  2. 通过 trait / interface 反转依赖方向(DIP), trait 放在使用方模块或单独模块而非实现方模块
  • 禁止语义耦合: 不得利用另一个模块的内部实现知识:
  • 不得因"知道"对方会自动初始化而跳过初始化调用
  • 不得因"知道"对方只用部分字段而只部分构造数据
  • 不得假设对方内部的全局/静态数据已被自己修改
  • 语义耦合的危险在于: 更改被依赖模块的代码会以编译器完全无法检测的方式破坏调用方
  • 禁止依赖不稳定模块: 模块的依赖方向必须指向更稳定的模块(被更多模块依赖的模块).
  • 不得让被广泛依赖的稳定模块依赖不稳定的模块
2.4 不得暴露实现细节
  • 模块的公开接口不得暴露内部数据结构的表示方式——使用 newtype 模式或封装
  • 不得在公开接口中暴露仅内部使用的函数或类型
  • 不得将私有实现细节放入模块接口声明

3. 模块必须达到的标准

3.1 功能内聚

模块必须达到功能内聚——模块内的所有项围绕一个单一的、明确的职责组织. 判断标准:

  • 能用一句话描述模块做什么(而不是"做X和Y和Z")
  • 模块名就是对其职责的精确描述(如 parser、config、auth)
  • 移除模块中任何一个项都会使模块的职责不完整

实证数据: 高内聚模块无故障率 50%, 低内聚模块仅 18%; 内聚-耦合比率最差的模块错误率高 7 倍, 修复成本高 20 倍.

3.2 无环依赖

模块依赖图必须是有向无环图(DAG). 每次新增或修改 use 依赖时必须验证不引入环路.

3.3 依赖方向正确

依赖必须指向更稳定的方向. 模块的"稳定性"由传入依赖数(Ca)和传出依赖数(Ce)决定:

  • I = Ce / (Ca + Ce), 取值 [0, 1], I 越小越稳定
  • 依赖 I 值比自己低的模块
3.4 稳定模块必须抽象

被大量模块依赖的稳定模块必须以抽象(trait)为主, 而非具体实现. 这样即使模块难以改变 (因大量传入依赖), 仍可通过扩展适应新需求. 具体原则:

  • 稳定模块(I 接近 0)应暴露 trait 和类型定义, 具体实现放在依赖它的不稳定模块中
  • 不稳定模块(I 接近 1)可以包含具体实现, 因为它们易于改变
  • 禁止出现"痛苦区"模块: 高度具体(A 接近 0)且大量传入依赖(I 接近 0)——这种模块

改变极其痛苦且无法通过扩展应对

3.5 共同闭合

因同一需求变化而必须同时修改的项, 必须放在同一个模块中(CCP). 这确保变化集中, 减少每个发布周期中受影响的模块数量. 一个模块不应有多个变化原因.

3.6 共同复用

总是一起被复用的项必须放在同一个模块中(CRP). 不一起复用的项不得放在同一模块. 对模块的依赖就是对模块内所有内容的依赖——模块中存在不被一起使用的项, 会导致无关项的 变化强制依赖方升级和重新验证.

4. 模块接口设计

4.1 最小化公开接口

模块的公开接口必须是最小必要集. 判断标准:

  • 不确定是否应该 pub 时, 就不 pub
  • 每增加一个 pub 项都要问: "这个项与模块的抽象一致吗? 去掉它模块职责是否完整?"
  • 通过组合少量精确定义的接口提供功能, 而非暴露大量细粒度操作
4.2 接口一致性

模块的公开接口必须呈现一致的抽象层次:

  • 所有 pub 项必须围绕同一个职责, 不得混入不同层次的关注点
  • 不得在模块接口中添加与现有抽象不一致的公共成员——每次添加时验证一致性
  • 成对提供服务: 有创建就有销毁, 有打开就有关闭, 有添加就有移除
4.3 接口程序化而非语义化

模块接口必须尽可能通过类型系统和编译器强制约束, 而非依赖调用方的语义理解:

  • 用类型(如 newtype、enum)代替裸基本类型, 让编译器捕获误用
  • 用必须调用的方法代替可选的初始化步骤(消除"忘记调用 init"的可能)
  • 将语义接口元素(调用方必须知道的隐式规则)转化为程序化接口元素(编译器可强制的约束)
4.4 信息隐藏

设计模块接口就是问"这个模块需要隐藏什么?". 两类秘密:

  1. 隐藏复杂性: 复杂数据结构、文件格式、算法细节——使调用方的大脑不需要处理
  2. 隐藏变化源: 当变化发生时影响被局部化——业务规则、硬件依赖、数据格式等

可能变化的区域必须被隐藏在接口之后:

  • 业务规则
  • 硬件或外部软件依赖
  • 输入输出格式
  • 状态变量(用访问函数而非直接暴露变量)
  • 数据大小约束(用命名常量而非硬编码)
4.5 抽象接口放在使用方

模块间的 trait (rust) / interface (go, java) 应放在使用它的模块中, 而 非实现它的模块中.

这使得依赖方向从"使用方→实现方"反转为"使用方→抽象接口, 实现方→抽象接口", 打破直接依赖环路, 并让抽象接口精确反映使用方的需求.

5. 模块层次结构设计

深模块: 简洁接口隐藏强大功能(如 Unix I/O: open/read/write/close 封装文件系统与io设备等多个复杂层次) 浅模块: 接口复杂度 ≈ 实现复杂度, 没有抽象价值

深模块优于浅模块

5.1 设计原则
  • 模块层级与目录层级必须对应:同层级模块放在同目录下,子模块放在子目录下
  • 例如:xxx.rs 模块的子模块放在 xxx/yyy.rs
  • 每个模块层级必须改变抽象, 而非仅转发调用
  • 必须按信息隐藏原则而不是按操作的执行顺序拆分模块
  • 如果信息隐藏原则造成模块过大,必须拆分成子模块,而不是拆成同层级的浅模块
5.2 判断标准

若去掉某模块层级后调用方几乎不需要多了解实现细节, 则该层级必须去掉. 例如 pass-through 反例:

// handler.rs — 该模块仅转发, 未改变抽象, 参数和返回值与下层完全一致
pub fn handle_user_query(id: u64) -> User { service::find_user(id) }
// service.rs — 该模块仅转发, 未改变抽象, 参数和返回值与下层完全一致
pub fn find_user(id: u64) -> User { repo::get_user(id) }
// repo.rs — 真正有意义的逻辑
pub fn get_user(id: u64) -> User {
let row = db.query("SELECT ...", &[id]);
User::from_row(row) // 这里改变了抽象: SQL Row → domain User
}
// handler 和 service 模块没有改变抽象, 应去掉, 直接用 repo 模块
// **注意**: 这是模块层级的判断标准, 不适用于函数调用等其他场景的层级判断

6. 模块测试规范

6.1 测试定义行为

测试模块是模块行为的唯一定义来源, 测试用例必须完整覆盖模块所有行为. 模块能做什么、 不能做什么、边界在哪里, 都由测试用例规定. 没有测试覆盖的行为可认为不存在.

  • 测试必须先于实现编写(TDD)——测试定义了模块应该做什么, 实现只是让测试通过
  • 测试用例即行为契约:
  • 正常路径定义"能做什么": 所有公共函数的输入输出、所有公共类型的构造与转换、

所有公共 trait 的行为

  • 错误路径定义"不能做什么": 非法输入、前置条件不满足、资源不可用
  • 边界条件定义"做到什么程度": 极值、空值、溢出、并发
  • 不变量(invariant)定义"始终成立的约束": 无论什么路径都不得违反
  • 测试用例必须从模块的外部可观察行为出发设计, 而非基于内部实现细节
  • 必须先同步更新测试以定义新的行为, 再变更模块的公开接口——不得出现测试与接口不一致
  • 禁止后向兼容测试: 删除即消失, 禁止测试被删除的旧行为, 即使只是验证它会失败
6.2 测试模块结构
  • 每个模块 xxx.rs 对应同目录下的 xxx_tests.rs, 测试用例数 >35 个则拆为 xxx_<子职责>_tests.rs
  • 测试模块禁止调用或依赖任何被测模块的内部实现,最多只允许调用被测模块的模块级公开接口
  • 被测模块内部不得包含任何测试代码——所有测试代码必须在 _tests.rs 文件中
  • 测试模块与被测模块必须是两个独立的模块, 通过被测模块的模块级公开接口交互, 实现模块级黑盒测试
  • 模块级测试必须放在被测模块的同目录下, 禁止放在被测模块的子目录下
  • 进程级测试属于集成测试, 必须端到端覆盖所有用户场景, 只能调用进程外部接口, 而不是代码级接口
  • 集成测试必须放在tests目录而不是src目录下, 与模块级测试区分开
6.3 测试用例命名
  • 格式: test_<操作>_<场景>, 如 test_login_invalid_password
  • 操作名对应被测的公开操作, 场景名描述具体行为或条件
  • 禁止模糊命名: test_function_1、test_edge_case、test_ok 均不合格

Security

  • Security scanPassed, 100 of 100Pattern checks on the skill's files.
  • Model reviewNot runA model review is scheduled for the next rescan.

Quality evaluation

  • Task evaluationNot runNo evaluation yet. Run one in Skill Studio.

Source

Popularity

Repository stars
110
Repository forks
9
7-day trend score
0

Stars and forks are for the whole GitHub repository, not this skill alone. Not refreshed yet.

Works with

Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.

  • Claude Code
  • Cursor
  • GitHub Copilot
  • Windsurf
  • Codex
  • Gemini CLI
  • Cline
  • Amp
  • Roo Code
  • Goose
  • Continue
  • Kilo Code
  • Junie
  • Trae
  • OpenHands
  • Qwen Code
  • AI Agent
  • Tabnine Chat
  • Sourcegraph Cody
  • Amazon Q
  • Firebase Genkit
  • Sweep
  • Devin
  • Phind
  • Mentat
  • Claude Desktop
  • Aider
  • GPT Pilot
  • Plandex
  • bolt.new
  • v0
  • Replit Agent
  • Anse
  • TypingMind
  • BetterChatGPT
  • LibreChat
  • Warp AI
  • Pieces
  • Fig AI
Embed badge
vskill VERIFIED badge
[![vskill VERIFIED](https://verified-skill.com/api/v1/skills/abadcafe/superteam/module-design/badge)](https://verified-skill.com/skills/abadcafe/superteam/module-design)

Something wrong with this skill or its page? Tell us.