在软件架构设计中,扇入(Fan-in)和扇出(Fan-out)用于衡量模块的依赖关系,直接影响系统的耦合度、可维护性和可扩展性。
1. 扇入(Fan-in)
定义
扇入表示有多少个上级模块调用当前模块,即该模块被引用的次数。
特点
-
高扇入(被多个模块调用)通常表示该模块复用性高,是通用功能(如工具类、公共服务)。
-
但过高扇入可能导致该模块成为瓶颈(修改影响范围大)。
-
优化建议:
-
高扇入模块应保持稳定,避免频繁修改。
-
如果扇入过高,可考虑拆分(如工具类按功能细分)。
-
2. 扇出(Fan-out)
定义
扇出表示当前模块直接依赖的下级模块数量,即它调用了多少其他模块。
特点
-
低扇出(依赖模块少)通常表示模块职责单一,符合单一职责原则(SRP)。
-
高扇出(依赖过多模块)可能导致:
-
紧耦合,修改影响大
-
测试复杂度高(需 Mock 多个依赖)
-
可维护性降低(牵一发而动全身)
-
-
优化建议:
-
扇出 ≤ 7(经验值,类似“人的短期记忆容量”)
-
高扇出时,可引入外观模式(Facade)或依赖倒置(DIP)减少直接依赖。
-
3. 扇入与扇出的平衡
理想情况
-
高扇入 + 低扇出(模块被广泛复用,自身依赖少) → 最稳定
-
低扇入 + 高扇出(模块很少被复用,但依赖众多) → 最不稳定
优化策略
情况 | 问题 | 优化方法 |
---|---|---|
扇入过高 | 修改影响大 | 拆分成更小模块 |
扇出过高 | 耦合度高 | 使用外观模式、依赖注入 |
扇入过低 | 复用性差 | 提取公共逻辑 |
扇出过低(极端情况) | 可能过度封装 | 适当合并相关逻辑 |
4. 实际应用示例
✅ 良好设计
plaintext
复制
下载
[订单服务] ←───┐ │ │ ↓ │ [支付模块] ←─── [日志模块](高扇入) │ ↓ [库存模块]
-
日志模块:高扇入(被多个模块调用),低扇出(仅依赖日志库)。
-
订单服务:扇出=2(支付+库存),合理。
❌ 糟糕设计
plaintext
复制
下载
[订单服务] │ ├─ [支付模块] ├─ [库存模块] ├─ [日志模块] ├─ [消息队列] ├─ [缓存服务] └─ ...(扇出=6+,过高)
-
订单服务扇出过高 → 应使用外观模式封装支付、库存等逻辑。
5. 总结
指标 | 定义 | 优化目标 | 风险 |
---|---|---|---|
扇入 | 被调用次数 | 适当高(提高复用) | 过高→修改影响大 |
扇出 | 依赖模块数 | 尽量低(≤7) | 过高→耦合度高 |
最佳实践:
✔ 复用高扇入模块(如工具类、通用服务)
✔ 控制扇出(避免依赖爆炸)
✔ 结合SOLID原则(单一职责、依赖倒置等)优化结构
通过合理控制扇入和扇出,可以显著提升软件的可维护性、可测试性和扩展性。