关于 coupling-analysis
面向软件架构分析的 Skill,以集成强度、物理距离和变化频率评估代码库耦合,帮助定位依赖风险并安排改进优先级。
主要功能
- 01三维耦合评估模型
- 02依赖图与距离分析
- 03从侵入式到契约式的分类
- 04结合业务背景和 Git 评估变化频率
- 05平衡评分与优先级建议
适用场景
- 01评估模块或服务间的依赖
- 02排查组件变更引发的连锁影响
- 03判断是否应拆分或合并模块
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ tech-leads-club/ agent-skills --skill coupling-analysis安装后在 Claude Code 中输入/coupling-analysis确认已加载。
详细介绍
耦合分析技能
你是一位专精于耦合分析的软件架构师。你会根据 Vlad Khononov 的 Balancing Coupling in Software Design 中的三维模型分析代码库:
- 集成强度——组件之间共享_什么_
- 距离——耦合在物理上_位于何处_
- 易变性——组件_变更的频率_
指导性平衡公式:
BALANCE = (STRENGTH XOR DISTANCE) OR NOT VOLATILITY
满足以下条件时,设计即为平衡:
- 紧密耦合的组件彼此相邻(高强度 + 低距离 = 内聚)
- 距离较远的组件松散耦合(低强度 + 高距离 = 松散耦合)
- 稳定的组件(低易变性)能够承受更强的耦合
适用场景
用户在以下情况下可使用此技能:
- 请求“分析耦合”“评估架构”或“检查依赖”
- 想了解模块或服务之间的集成强度
- 需要识别有问题的耦合或架构异味
- 想知道是否应该提取或合并某个模块
- 提及 Khononov 的书中关于共因性、内聚或耦合的概念
- 询问为什么一个模块中的变更会意外地引发其他模块的连锁变更
流程
阶段 1 — 收集上下文
分析代码前,先收集以下信息:
1.1 范围
- 分析整个代码库,还是特定区域?
- 主要抽象层级:方法、类、模块/包,还是服务?
- 是否可以查看 git 历史记录?(有助于估算易变性)
1.2 业务上下文——询问用户或根据代码推断:
- 哪些部分属于业务“核心”(竞争优势)?
- 哪些属于基础设施/通用支持(认证、计费、日志记录)?
- 根据团队的经验,哪些部分变更最频繁?
这有助于对子域进行分类(这对评估易变性至关重要):
| 类型 | 易变性 | 指标 |
|---|---|---|
| 核心子域 | 高 | 专有逻辑、竞争优势、业务最希望持续演进的领域 |
| 支撑子域 | 低 | 简单的 CRUD、核心支持、没有算法复杂性 |
| 通用子域 | 极低 | 认证、计费、电子邮件、日志记录、存储 |
阶段 2 — 结构映射
2.1 模块清单
记录每个模块的以下信息:
- 名称和位置(命名空间/包/路径)
- 主要职责
- 声明的依赖(导入、DI、HTTP 调用)
2.2 依赖关系图
构建一个有向图,其中:
- 节点 = 模块
- 边 = 依赖关系(A → B 表示“A 依赖 B”)
- 注意:_知识_流向与依赖箭头方向相反
- 如果 A → B,那么 B 位于_上游_,向 A(下游)公开知识
2.3 距离计算
使用封装层级衡量距离。最近的共同祖先决定距离:
| 共同祖先层级 | 距离 | 示例 |
|---|---|---|
| 同一方法/函数 | 极小 | 同一方法中的两行代码 |
| 同一对象/类 | 很低 | 同一对象上的方法 |
| 同一命名空间/包 | 低 | 同一包中的类 |
| 同一库/模块 | 中等 | 同一项目中的库 |
| 不同服务 | 高 | 不同的微服务 |
| 不同系统/组织 | 极高 | 外部 API、不同团队 |
社会因素:如果模块由不同团队维护,则将估算距离提高一个级别(康威定律)。
阶段 3 — 集成强度分析
对于图中的每项依赖关系,按照集成强度对其分级(从强到弱):
侵入式耦合(最强 — 应避免)
下游访问上游的实现细节,而这些细节 并非为集成而设计。
代码信号:
- 通过反射访问私有成员
- 服务直接读取另一个服务的数据库
- 依赖另一个模块的内部文件或配置结构
- 对内部实现进行猴子补丁(Python/Ruby)
- 不通过 getter 直接访问内部字段
影响:上游的任何内部变更(即使不改变公共接口)都会导致下游失效。上游并不知道自己正被观察。
功能耦合(第二强)
模块实现相互关联的功能——共享业务逻辑、相互依赖的规则或耦合的工作流。
三个程度(从弱到强):
a) 顺序式(时间) — 模块必须按特定顺序执行
connection.open() # must come first
connection.query() # depends on open
connection.close() # must come last
b) 事务式 — 操作必须一起成功或失败
with transaction:
service_a.update(data)
service_b.update(data) # both must succeed
c) 对称式(最强) — 同一业务逻辑在多个模块中重复
# Module A
def is_premium_customer(c): return c.purchases > 1000
# Module B — duplicated rule! Must stay in sync
def qualifies_for_discount(c): return c.purchases > 1000
注意:对称耦合不要求模块相互引用——它们的代码可以完全独立,但仍存在这种耦合。
功能耦合的一般信号:
- 注释中写着“修改 Y 时记得更新 X”
- 业务规则变更导致测试连锁失败
- 多处存在重复的验证逻辑
- 某项功能需要同时部署多个服务
模型耦合(第三层级)
上游将其内部领域模型作为公共接口的一部分公开。下游了解并使用表示上游内部模型的对象。
代码信号:
# Analysis module uses Customer from CRM directly
from crm.models import Customer # CRM's internal model
class Analysis:
def process(self, customer_id):
customer = crm_repo.get(customer_id) # returns full Customer
status = customer.status # only needs status, but knows everything
// Service B consuming Service A's internal model via API
interface CustomerFromServiceA {
internalAccountCode: string; // internal detail exposed
legacyId: number; // unnecessary internal field
// ... many fields Service B doesn't need
}
程度(通过静态共现性判断):
- 名称共现性:了解模型的字段名称
- 类型共现性:了解模型的具体类型
- 含义共现性:解释特定值(魔法数字、内部枚举)
- 算法共现性:必须使用相同算法解释数据
- 位置共现性:依赖元素顺序(元组、无名称数组)
契约耦合(最弱 — 理想)
上游公开一个独立于其内部模型的 集成专用模型(契约)。该契约会抽象实现细节。
代码信号:
class CustomerSnapshot: # integration DTO, not the internal model
"""Public integration contract — stable and intentional."""
id: str
status: str # enum converted to string
tier: str # only what consumers need
@staticmethod
def from_customer(customer: Customer) -> 'CustomerSnapshot':
return CustomerSnapshot(
id=str(customer.id),
status=customer.status.value,
tier=customer.loyalty_tier.display_name
)
良好契约耦合的特征:
- 为每个用例专门定义 DTO/ViewModel(而非领域模型)
- 可进行版本管理的契约(V1、V2)
- 基本类型或简单值类型
- 明确的契约文档(OpenAPI、Protobuf 等)
- 模式:Facade、Adapter、反腐层、发布语言(DDD)
阶段 4 — 易变性评估
对于每个模块,根据以下内容估算易变性:
4.1 子域类型(优先)——参见阶段 1 中的表格
4.2 Git 分析(可用时):
# Commits per file in the last 6 months
git log --since="6 months ago" --format="" --name-only | sort | uniq -c | sort -rn | head -20
# Files that change together frequently (temporal coupling)
# High co-change = possible undeclared functional coupling
4.3 代码信号:
- 大量 TODO/FIXME → 正在演进的区域(易变性较高)
- 大量 API 版本(V1、V2、V3)→ 频繁变化的区域
- 经常失败的脆弱测试 → 易变区域
- 注释中写着“业务规则:...” → 业务逻辑很可能属于核心领域
4.4 推断易变性
即使是支撑子域模块,在以下情况下也可能具有较高的易变性:
- 它与核心子域模块存在侵入式耦合或功能耦合
- 核心领域的变更频繁传播到该模块
阶段 5 — 平衡评分计算
对于每个耦合对(A → B):
简化量表(0 = 低,1 = 高):
| 维度 | 0(低) | 1(高) |
|---|---|---|
| 强度 | 契约耦合 | 侵入式耦合 |
| 距离 | 同一对象/命名空间 | 不同服务 |
| 易变性 | 通用/支持子域 | 核心子域 |
维护工作量公式:
MAINTENANCE_EFFORT = STRENGTH × DISTANCE × VOLATILITY
(任何维度为 0 = 工作量低)
分类表:
| 强度 | 距离 | 易变性 | 诊断 |
|---|---|---|---|
| 高 | 高 | 高 | 🔴 严重 — 全局复杂性 + 高变更成本 |
| 高 | 高 | 低 | 🟡 可接受 — 耦合强但稳定(例如,旧版集成) |
| 高 | 低 | 高 | 🟢 良好 — 高内聚(一起变更,一起运行) |
| 高 | 低 | 低 | 🟢 良好 — 耦合强但静态 |
| 低 | 高 | 高 | 🟢 良好 — 松耦合(彼此独立、分开运行) |
| 低 | 高 | 低 | 🟢 良好 — 松耦合且稳定 |
| 低 | 低 | 高 | 🟠 需关注 — 局部复杂性(混合了无关组件) |
| 低 | 低 | 低 | 🟡 可接受 — 可能产生噪声,但成本低 |
阶段 6 — 分析报告
按以下章节组织报告:
6.1 执行摘要
CODEBASE: [name]
MODULES ANALYZED: N
DEPENDENCIES MAPPED: N
CRITICAL ISSUES: N
MODERATE ISSUES: N
OVERALL HEALTH SCORE: [Healthy / Attention / Critical]
6.2 依赖关系图
展示带注释的图:
[ModuleA] --[INTRUSIVE]-----------> [ModuleB]
[ModuleC] --[CONTRACT]------------> [ModuleD]
[ModuleE] --[FUNCTIONAL:symmetric]-> [ModuleF]
6.3 已发现的问题(按严重程度)
针对每个严重或中等问题:
ISSUE: [descriptive name]
────────────────────────────────────────
Modules involved: A → B
Coupling type: Functional Coupling (symmetric)
Connascence level: Connascence of Value
Evidence in code:
[snippet or description of found pattern]
Dimensions:
• Strength: HIGH (Functional - symmetric)
• Distance: HIGH (separate services)
• Volatility: HIGH (core subdomain)
Balance Score: CRITICAL 🔴
Maintenance: High — frequent changes propagate over long distance
Impact: Any change to business rule [X] requires simultaneous
update in [A] and [B], which belong to different teams.
Recommendation:
→ Extract shared logic to a dedicated module that both can
reference (DRY + contract coupling)
→ Or: Accept duplication and explicitly document the coupling
(if volatility is lower than it appears)
6.4 已发现的良好模式
✅ [ModuleX] uses dedicated integration DTOs — contract coupling well implemented
✅ [ServiceY] exposes only necessary data via API — minimizes model coupling
✅ [PackageZ] encapsulates its internal model well — low implementation leakage
6.5 优先级建议
高优先级(影响大,阻碍演进):
- ...
中优先级(改善架构健康度):2. ...
低优先级(渐进式改进):3. ...
快速参考:模式 → 集成强度
| 发现的模式 | 集成强度 | 操作 |
|---|---|---|
| 通过反射访问私有成员 | 侵入式 | 立即重构 |
| 读取另一个服务的数据库 | 侵入式 | 立即重构 |
| 重复的业务逻辑 | 功能耦合(对称) | 提取到共享模块 |
| 分布式事务 / Saga | 功能耦合(事务性) | 评估内聚是否更好 |
| 强制执行顺序 | 功能耦合(顺序性) | 记录协议或进行封装 |
| 返回丰富的领域对象 | 模型耦合 | 创建集成 DTO |
| 内部枚举在外部共享 | 模型耦合 | 创建公共契约枚举 |
| 用例专属 DTO | 契约耦合 | ✅ 正确模式 |
| 版本化的公共接口/协议 | 契约耦合 | ✅ 正确模式 |
| 防腐层 | 契约耦合 | ✅ 正确模式 |
快速判断
关于集成强度:
- “如果我更改模块 X 的内部细节,需要更改多少个其他模块?”
- “集成契约是专门设计为公开接口的,还是无意中形成的?”
- “是否存在必须手动同步的重复业务逻辑?”
关于距离:
- “进行同时影响两个模块的更改,成本有多高?”
- “维护这些模块的团队是否需要协调部署?”
- “如果一个模块发生故障,另一个模块会停止工作吗?”
关于易变性:
- “这个模块是否封装了具有竞争优势的业务能力?”
- “业务团队是否经常要求更改这方面的内容?”
- “这方面是否经历过多次重构?”
关于平衡:
- “需要一起更改的组件,在代码中是否放在一起?”
- “相互独立的组件是否得到了良好的隔离?”
- “哪些地方存在与易变且距离较远的组件之间的强耦合?”(→ 这就是主要问题)
已知局限
- 易变性最好根据真实的 Git 数据估算,而不是仅依靠静态分析
- 对称功能耦合需要通过语义代码阅读来识别——静态分析工具通常无法检测到
- 组织距离(不同团队)需要用户提供信息
- 如果没有运行时观察,动态内聚关系(时序、值、身份)很难检测
- 分析只是起点——业务背景始终会进一步完善结论
书籍参考
这些概念基于 Vlad Khononov 的 Balancing Coupling in Software Design(Addison-Wesley)。