05-Git 仓库蒸馏术:从代码仓库到 OpenClaw 虚拟人-代码结构分析
05 代码结构分析:模块、依赖、架构识别
这是《Git 仓库蒸馏术:从代码仓库到 OpenClaw 虚拟人》系列的第 5 篇。第 04 篇从提交历史还原了项目的"时间轴",这一篇转向"空间轴"——从静态代码里识别出系统的架构。提交历史告诉你系统怎么长成的,代码结构告诉你系统现在长什么样、各部分怎么咬合。
一、为什么代码结构分析是蒸馏的"骨架"
演进报告是时间轴,架构文档是空间骨架。两者结合,才构成对系统的完整认知。
代码结构分析要回答三个问题:
| 问题 | 关注点 | 对应产出 |
|---|---|---|
| 模块怎么划分 | 目录/包的组织逻辑 | 模块清单 |
| 模块间怎么依赖 | 谁依赖谁、有没有环 | 依赖图 |
| 架构是什么模式 | 分层?微服务?插件化? | 架构模式识别 |
这三个问题回答完,你就得到了一份"架构文档"——后续的文档蒸馏、模式提炼、知识图谱构建,都建立在这份架构文档之上。
二、模块划分与依赖关系
2.1 从目录结构识别模块
第 03 篇我们用 tree 看了目录,这一篇要更进一步——判断目录划分背后的逻辑。
# 看 3 层目录结构
tree -L 3 -d -I "node_modules|.git|dist|build|__pycache__"
常见的模块划分逻辑:
| 划分逻辑 | 特征 | 示例 |
|---|---|---|
| 按层划分 | 按技术职责分层 | api/、components/、utils/、views/ |
| 按业务划分 | 按业务领域分模块 | order/、user/、payment/ |
| 按功能划分 | 按功能点分模块 | auth/、dashboard/、settings/ |
| 混合划分 | 层 + 业务混合 | src/features/order/ 内含 api/、components/ |
判断方法:看顶层目录的命名。如果顶层是 api、components、utils,是按层;如果顶层是 order、user、payment,是按业务。
2.2 用 madge 分析模块依赖
madge 是分析 JS/TS 模块依赖的利器,能生成依赖图并检测循环依赖:
# 安装
npm install -g madge
# 分析依赖,输出依赖树
madge --extensions ts,tsx src/
# 检测循环依赖
madge --circular --extensions ts,tsx src/
# 生成依赖图(SVG)
madge --image deps.svg --extensions ts,tsx src/
输出示例(循环依赖检测):
✖ Found 3 circular dependencies!
1) src/core/model-service.ts > src/core/model-registry.ts > src/core/model-service.ts
2) src/api/client.ts > src/utils/request.ts > src/api/client.ts
3) src/views/dashboard/index.vue > src/components/chart-panel.vue > src/views/dashboard/index.vue
循环依赖是架构坏味道:它意味着模块边界不清晰,改一处可能引发连锁反应。循环依赖集中的区域,往往是技术债聚集地。
2.3 用 dependency-cruiser 做规则校验
dependency-cruiser 比 madge 更强大,支持自定义依赖规则:
# 安装
npm install -g dependency-cruiser
# 生成配置文件
depcruise --init
# 校验依赖规则
depcruise src/ --config .dependency-cruiser.js
配置文件示例(.dependency-cruiser.js):
module.exports = {
forbidden: [
{
name: 'no-circular',
severity: 'error',
from: {},
to: { circular: true }
},
{
name: 'no-utils-import-core',
severity: 'warn',
from: { path: '^src/utils' },
to: { path: '^src/core' }
},
{
name: 'no-views-import-api',
severity: 'warn',
from: { path: '^src/views' },
to: { path: '^src/api' }
}
]
};
规则校验的价值:把"架构约定"变成"可执行的检查",防止架构腐化。这也是蒸馏出的架构文档能"活"下去的关键——不是纸面文档,而是可校验的规则。
2.4 Python 项目的依赖分析
Python 项目用 pydeps 或 import-linter:
# 安装 pydeps
pip install pydeps
# 生成模块依赖图
pydeps src/ --max-bonds=10
# 安装 import-linter(架构规则校验)
pip install import-linter
# 配置 .importlinter
cat > .import-linter << 'EOF'
[importlinter]
root_package = myapp
[importlinter:contract:1]
name = Core 不依赖 Utils
type = layers
layers =
core
utils
EOF
# 校验
lint-imports
三、架构模式识别
3.1 常见架构模式特征
从代码结构特征反推架构模式:
| 架构模式 | 代码特征 | 识别信号 |
|---|---|---|
| 分层架构 | 目录按层划分,依赖单向 | api → service → dao 单向依赖 |
| 微服务 | 多仓库/多服务目录,独立部署 | 每个服务有独立 package.json/Dockerfile |
| 插件化 | 核心 + 插件目录,注册机制 | plugins/ 目录 + 注册表/接口约定 |
| 事件驱动 | 事件总线、消息队列 | event-bus、publisher、subscriber |
| 六边形/端口适配器 | 核心业务与外部隔离 | domain/、ports/、adapters/ 目录 |
3.2 识别信号的具体命令
# 看是否有多个独立服务(微服务信号)
find . -name "package.json" -not -path "*/node_modules/*" | head -20
# 看是否有 Dockerfile(部署单元信号)
find . -name "Dockerfile" -not -path "*/node_modules/*"
# 看是否有插件注册机制
grep -r "registerPlugin\|pluginRegistry\|addPlugin" src/ --include="*.ts" -l
# 看是否有事件总线
grep -r "EventBus\|eventBus\|emit(" src/ --include="*.ts" -l | head -10
3.3 用 git log 验证架构模式
架构模式不是"看起来像"就行,还要看它是否"真的这么演进":
# 看核心目录的提交历史,验证模块是否稳定
git log --oneline -- src/core/ | head -20
# 看某个模块是否频繁变动(不稳定模块信号)
git log --oneline -- src/views/dashboard/ | wc -l
判断标准:
- 核心模块提交少、稳定 → 架构健康
- 某个模块提交极多 → 可能是"上帝模块"(什么都往里塞)
- 目录结构频繁重组 → 架构还在探索期
四、核心模块与边界
4.1 识别核心模块
核心模块是系统的"心脏",识别方法:
# 方法1:按依赖被引用次数(被依赖最多的模块是核心)
# 用 madge 输出 JSON 后统计
madge --json --extensions ts,tsx src/ > deps.json
# 方法2:按提交频率(改动最多的模块)
git log --name-only --pretty=format: | grep "^src/" | cut -d/ -f1-2 | sort | uniq -c | sort -rn | head -10
输出示例:
1890 src/core/
1450 src/api/
1200 src/components/
890 src/views/
450 src/utils/
核心模块特征:被依赖多 + 提交频繁 + 业务逻辑集中。src/core/ 就是典型的核心模块。
4.2 识别模块边界
模块边界是"哪些东西属于这个模块,哪些不属于"。判断方法:
# 看模块内部文件是否内聚(是否只做一件事)
ls src/core/
# 输出: model-service.ts model-registry.ts model-loader.ts
# 内聚:都是模型相关
# 看模块间是否有"越界"引用
grep -r "from '../views'" src/core/ --include="*.ts"
# 如果 core 引用了 views,说明边界被破坏
边界被破坏的信号:
- 核心模块引用了 UI 模块(
core依赖views) - 工具模块引用了业务模块(
utils依赖core) - 模块间互相引用形成环
4.3 用 git log --follow 追踪模块演进
# 追踪核心模块的目录演进
git log --oneline --follow -- src/core/
# 看核心模块是否被拆分过
git log --diff-filter=D --name-only -- src/core/ | head -20
模块演进的价值:一个模块从"单体"拆成"多个子模块",往往对应一次架构决策——这是决策记录(第 08 篇)的重要素材。
五、输出架构文档
分析完成后,把发现整理成"架构文档"。这是蒸馏流程的第三个正式产出物。
5.1 架构文档模板
# 架构文档:xxx
## 架构概览
- 架构模式:分层架构(UI → 业务 → 数据)
- 技术栈:Vue 3 + TypeScript + Pinia + Element Plus
- 部署形态:单页应用(SPA)
## 模块清单
| 模块 | 职责 | 依赖 | 稳定性 |
|------|------|------|--------|
| src/core/ | 核心业务逻辑 | 无外部依赖 | 高(稳定) |
| src/api/ | 接口封装 | core | 中 |
| src/components/ | 通用 UI 组件 | 无 | 高 |
| src/views/ | 页面 | api、components | 低(频繁变动) |
| src/utils/ | 工具函数 | 无 | 中 |
## 依赖关系
- 依赖方向:views → api → core(单向)
- 循环依赖:3 处(详见下方"风险")
- 核心模块:src/core/(被 4 个模块依赖)
## 架构模式
- 分层:UI 层(views/components)→ 业务层(core)→ 数据层(api)
- 状态管理:Pinia(全局 store)
- 组件通信:props/events + Pinia
## 模块边界
- 边界规则:
- views 不得直接依赖 core(应通过 api)
- utils 不得依赖任何业务模块
- 禁止循环依赖
- 边界破坏:2 处(utils 引用了 core)
## 风险与建议
- 循环依赖 3 处:建议拆分 model-service 与 model-registry
- utils 引用 core:建议将相关函数下沉到 core
- views 模块过大:建议按业务拆分子模块
## 可执行规则
- 已用 dependency-cruiser 固化边界规则(见 .dependency-cruiser.js)
- CI 中运行 depcruise 校验,防止架构腐化
5.2 架构文档的用途
架构文档是蒸馏流程的空间骨架:
- 给 06 文档蒸馏:知道哪些模块的文档最值得写
- 给 07 模式提炼:模块边界 = 模式应用的上下文
- 给 09 知识图谱:模块关系是图谱的节点和边
- 给 12 虚拟人化:架构文档是虚拟人 memory 的"系统认知"部分
六、小结
这一篇的核心收获:
- 模块划分:从目录结构识别划分逻辑(按层/按业务/按功能/混合)。
- 依赖分析:用
madge检测循环依赖,用dependency-cruiser固化架构规则。 - 架构模式识别:从代码特征反推模式(分层/微服务/插件化/事件驱动),并用提交历史验证。
- 核心模块与边界:用依赖引用数和提交频率识别核心模块,用越界引用检测边界破坏。
- 输出架构文档:一份带模块清单、依赖图、边界规则、可执行校验的架构文档。
下一篇,我们开始"蒸馏"文档:[06 文档蒸馏:从 issue、PR、README 提炼知识](06-Git 仓库蒸馏术:从代码仓库到 OpenClaw 虚拟人-文档蒸馏.md)——把散落在 issue、PR、注释里的知识,提炼成结构化的文档。
上一篇:[04 提交历史挖掘:从 commit 提炼演进脉络](04-Git 仓库蒸馏术:从代码仓库到 OpenClaw 虚拟人-提交历史挖掘.md)
下一篇:[06 文档蒸馏:从 issue、PR、README 提炼知识](06-Git 仓库蒸馏术:从代码仓库到 OpenClaw 虚拟人-文档蒸馏.md)
更多推荐



所有评论(0)