12 KiB
12 KiB
架构分析方法论
本文档提供代码库架构分析的核心方法论和最佳实践。
目录
1. 子系统边界识别
规则 1: 目录命名模式
通过目录名称识别子系统:
| 目录模式 | 子系统类型 | 常见技术栈 |
|---|---|---|
frontend/, ui/, web/, client/ |
前端子系统 | React, Vue, Angular |
backend/, api/, server/ |
后端子系统 | FastAPI, Express, Django |
agent/, agents/, workers/ |
Agent 系统 | LangGraph, CrewAI, Celery |
services/ + 多个子目录 |
微服务集群 | Spring Boot, Go microservices |
database/, models/, schema/ |
数据层 | SQLAlchemy, Prisma |
shared/, common/, lib/ |
共享库 | 工具函数、类型定义 |
规则 2: 独立配置文件识别
每个子系统通常有独立的配置文件:
frontend/
├── package.json → 独立的 Node.js 项目
├── tsconfig.json
└── vite.config.js
backend/
├── requirements.txt → 独立的 Python 项目
├── pyproject.toml
└── Dockerfile
识别方法:
# 查找独立的依赖文件
find . -name "package.json" -o -name "requirements.txt" -o -name "go.mod"
规则 3: Docker Compose 服务划分
分析 docker-compose.yml 识别服务边界:
services:
frontend: # 前端服务
build: ./frontend
api: # API 服务
build: ./backend
worker: # 后台任务
build: ./worker
db: # 数据库
image: postgres:15
每个 service 通常对应一个独立的子系统。
2. 工作流模式识别
模式 1: Multi-Agent 编排
特征:
- 导入
langgraph,crewai,autogen - 存在
StateGraph(),Crew(),Sequential()调用 - 使用
add_node(),add_edge()方法
提取方法:
-
定位编排定义
grep -r "StateGraph\|Crew\|AutoGen" --include="*.py" -
提取 Agent 节点
# 示例代码 graph = StateGraph(AgentState) graph.add_node("researcher", research_agent) # Agent 1 graph.add_node("writer", writing_agent) # Agent 2 graph.add_node("reviewer", review_agent) # Agent 3 -
分析状态流转
graph.add_edge("researcher", "writer") # 顺序流转 graph.add_conditional_edges("writer", should_revise, { "revise": "researcher", # 条件分支 "finish": END })
生成图表类型: stateDiagram-v2
模式 2: 数据管道(ETL/Pipeline)
特征:
- 目录名包含
pipeline,etl,workflow - 函数名包含
extract,transform,load - 使用 Airflow, Prefect, Dagster 框架
提取方法:
-
识别管道阶段
# 示例代码 def run_pipeline(source): raw = extract(source) # 阶段 1 clean = transform(raw) # 阶段 2 load(clean) # 阶段 3 -
追踪数据转换
- 输入:CSV 文件
- → DataFrame (pandas)
- → 清洗后 DataFrame
- → PostgreSQL 表
生成图表类型: flowchart LR (从左到右)
模式 3: 事件驱动架构
特征:
- 使用
EventEmitter,event_bus,@subscribe - 发布订阅模式:
emit(),on(),subscribe() - 消息队列:RabbitMQ, Kafka, Redis Pub/Sub
提取方法:
-
识别事件定义
# 发布事件 event_bus.emit("order_created", order) -
识别订阅者
@event_bus.on("order_created") def handle_order(order): send_confirmation(order) @event_bus.on("order_created") def update_inventory(order): inventory.decrease(order.items)
生成图表类型: graph TB (显示发布-订阅关系)
模式 4: 微服务调用链
特征:
docker-compose.yml中有多个 services- 使用
requests.get(),httpx.get()调用其他服务 - gRPC 调用:
stub.MethodCall()
提取方法:
-
识别服务间调用
# api-gateway 调用其他服务 user = requests.get("http://user-service/users/{id}") order = requests.post("http://order-service/orders", ...) -
绘制调用拓扑
- api-gateway → user-service
- api-gateway → order-service
- order-service → payment-service
生成图表类型: graph TB (服务拓扑)
模式 5: 传统分层架构(MVC)
特征:
- 目录结构:
controllers/,services/,models/ - 装饰器:
@app.route,@Controller - ORM 使用:SQLAlchemy, Sequelize
提取方法:
-
识别三层结构
- Controller: 处理 HTTP 请求
- Service: 业务逻辑
- Model: 数据模型
-
追踪调用链
routes.py (@app.route) → UserService.create() → User model → Database
生成图表类型: graph TD (分层图)
3. 通信机制识别
HTTP/REST API
搜索关键词:
# 服务端
grep -r "@app\.(get|post|put|delete)" --include="*.py"
grep -r "router\.(get|post)" --include="*.js"
grep -r "@RestController" --include="*.java"
# 客户端
grep -r "axios\.(get|post)" --include="*.js"
grep -r "requests\.(get|post)" --include="*.py"
grep -r "fetch(" --include="*.ts"
WebSocket
搜索关键词:
grep -r "WebSocket\|socket.io\|ws://" --include="*.{py,js,ts}"
消息队列
搜索关键词:
# RabbitMQ
grep -r "pika\|RabbitMQ" --include="*.py"
# Kafka
grep -r "kafka\|KafkaProducer" --include="*.{py,java}"
# Redis Pub/Sub
grep -r "redis.*publish\|redis.*subscribe" --include="*.py"
gRPC
搜索关键词:
grep -r "grpc\|\.proto" --include="*.{py,go,java}"
4. Mermaid 图表选择策略
根据识别到的模式选择合适的图表类型:
| 场景 | 图表类型 | 适用情况 |
|---|---|---|
| 状态转换明显(Multi-Agent) | stateDiagram-v2 |
有明确的状态节点和转换条件 |
| 顺序+条件流程(业务流程) | flowchart TD |
顺序执行 + if/else 分支 |
| 数据管道(ETL) | flowchart LR |
线性的数据转换流程 |
| 系统拓扑(微服务) | graph TB |
多个系统/服务的交互关系 |
| 时序交互(API 调用) | sequenceDiagram |
多个参与者的时序消息传递 |
| 并发任务 | graph TB + subgraph |
多个并行任务分组 |
语法注意事项
⚠️ Mermaid 语法约束(基于版本 11.x):
- stateDiagram-v2: 禁用
--分隔符(会报错 "No such shape: divider") - stateDiagram-v2: 不支持
<br/>标签 - sequenceDiagram:
alt/loop/par块必须正确配对end - 所有类型: 避免过深嵌套的控制结构
stateDiagram-v2 限制:
- ❌ 不支持
<br/>标签,使用note块代替 - ❌ 不支持
--分隔符 - ❌ 标签文本避免
!=,==等比较运算符 - ✅ 复杂信息放在
note right/left of NodeName块中
flowchart/graph:
- ✅ 可使用
<br/>换行 - ✅ 支持富文本标签
- ✅ 使用
style设置节点颜色
示例:选择决策树
检测到的特征:
├─ 有状态变量 + 转换逻辑?
│ → 是:使用 stateDiagram-v2
│ → 否:继续判断
│
├─ 有多个参与者 + 时序消息?
│ → 是:使用 sequenceDiagram
│ → 否:继续判断
│
├─ 线性数据转换?
│ → 是:使用 flowchart LR
│ → 否:继续判断
│
└─ 默认:使用 graph TB 或 flowchart TD
5. 业务函数识别规则
排除辅助函数
规则:以下函数不算业务逻辑
# 1. 私有函数(下划线开头)
def _internal_helper():
pass
# 2. 工具函数
def format_date(date):
pass
def validate_email(email):
pass
# 3. Getter/Setter
def get_user():
pass
def set_config():
pass
# 4. 过短的函数(< 5 行)
def simple_wrapper():
return another_function()
识别业务函数
特征 1:函数名包含业务关键词
业务动词:
- process_*, handle_*, execute_*, run_*
- create_*, update_*, delete_*
- generate_*, analyze_*, calculate_*
- search_*, fetch_*, query_*
- build_*, transform_*, convert_*
特征 2:处理核心数据模型
# 函数参数或返回值包含核心数据类
def process_order(order: Order) -> OrderResult: # ✓ 业务函数
...
def format_string(s: str) -> str: # ✗ 工具函数
...
特征 3:函数体较长(> 10 行)
通常业务逻辑较复杂,函数体较长。
特征 4:调用外部服务或数据库
def create_user(data):
user = User(**data)
db.session.add(user) # ✓ 数据库操作
db.session.commit()
send_email(user.email) # ✓ 外部服务
return user
6. 调用链追踪深度控制
最大深度策略
问题:递归追踪可能陷入无限循环
解决方案:限制最大深度
MAX_DEPTH = 5 # 最多追踪 5 层
def trace_calls(func_name, current_depth=0):
if current_depth >= MAX_DEPTH:
return
calls = extract_function_calls(func_name)
for call in calls:
trace_calls(call, current_depth + 1)
广度优先 vs 深度优先
广度优先(BFS):
- 优先展示同一层级的所有函数
- 适合识别并发任务
深度优先(DFS):
- 优先追踪单一调用链
- 适合追踪数据转换流程
推荐:对于流程分析,使用 广度优先。
7. 最佳实践
✅ 应该做的
- 先宽后深 - 先了解整体结构,再深入细节
- 只读分析 - 不修改任何代码
- 标注位置 - 所有结论都附带文件:行号
- 可视化优先 - 用图表表达复杂关系
- 分阶段输出 - 边分析边展示进度
❌ 不应该做的
- 不要臆测 - 所有结论必须基于代码事实
- 不要分析 node_modules/ - 跳过第三方依赖
- 不要暴露敏感信息 - 不读取
.env,secrets.yaml - 不要过度深入 - 不需要分析每一个辅助函数
- 不要修改代码 - 纯只读分析
8. 故障排除
问题 1: 找不到入口点
症状:无法识别主函数
解决方案:
# 多种方式查找
grep -r "if __name__ == '__main__'" --include="*.py"
grep -r "@app.route\|@app.post" --include="*.py"
grep -r "func main()" --include="*.go"
ls -la | grep -i "main\|index\|app"
问题 2: 调用链太复杂
症状:函数调用超过 100 层
解决方案:
- 只追踪业务函数,忽略工具函数
- 限制最大深度为 5
- 聚焦核心路径(最常用的调用链)
问题 3: 动态导入无法追踪
症状:Python 的 importlib, JavaScript 的 require(variable)
解决方案:
- 结合运行时日志分析
- 搜索字符串模式猜测可能的模块名
- 在报告中标注"动态导入,无法静态分析"
9. 工具推荐
Python 项目
ast模块 - 解析 Python ASTradon- 复杂度分析pydeps- 依赖可视化
JavaScript/TypeScript 项目
@typescript-eslint/parser- 解析 TS ASTmadge- 依赖关系图dependency-cruiser- 依赖验证
Go 项目
go-callvis- 调用图可视化gocyclo- 圈复杂度
通用工具
tree- 目录结构可视化tokei- 代码统计cloc- 代码行数统计
10. 参考资源
- C4 模型: 系统架构可视化的四层模型
- UML 类图: 面向对象系统的标准表示
- 事件风暴: 领域驱动设计的建模方法
- 架构决策记录 (ADR): 记录架构决策的最佳实践