第 1 章:依赖方向与系统耦合度

1.1 依赖方向的定义

依赖方向决定架构弹性。正向依赖(数据流与依赖流一致)导致紧耦合。反向依赖(数据流与依赖流相反)实现松耦合和可测试性。

方面正向依赖反向依赖 (DIP)
数据流从高层流向低层从低层流向高层
依赖流从高层流向低层高层和低层都流向抽象
耦合度高(运行时和编译时绑定)低(编译时分离,运行时多态)
可测试性低(难以模拟低层模块)高(易于通过接口注入模拟对象)

1.2 模块边界与职责

清晰的模块边界依赖稳定的抽象接口。接口属于高层(调用方),而非低层(实现方)。

核心职责分离:
高层模块:定义业务流程与策略,声明所需接口。
低层模块:实现具体技术细节(数据库、IO、第三方库)。
信任链路:高层信任低层遵守接口契约,低层信任高层定义的接口稳定不变。

1.3 耦合度量化指标

  • 扇出 (Fan-out): 一个模块直接依赖的其他模块数量。扇出高则耦合度高。
  • 扇入 (Fan-in): 依赖该模块的其他模块数量。扇入高表示模块被复用,不一定代表高耦合。
  • 不稳定性 (Instability): I = 扇出 / (扇入 + 扇出)。值越接近 1,模块越不稳定,越容易被变更影响。
  • 抽象程度 (Abstractness): A = 抽象元素数 / 总元素数。稳定的模块应具有高抽象程度。

1.4 选型权衡与风险点

风险点 1: 循环依赖。模块 A 依赖 B,B 依赖 A。导致构建失败或运行时死循环。必须通过引入抽象接口打破循环。
风险点 2: 依赖膨胀。模块泄漏内部依赖到外部,导致不必要的重新编译和部署。
解决策略: 严格依赖方向控制,应用依赖倒置原则 (DIP),强制接口属于客户方。

1.5 落地步骤与验收标准

  1. 识别模块间的数据流和信任链路。
  2. 提取高层模块需要的抽象接口。
  3. 反转依赖方向:高层依赖接口,低层实现接口。
  4. 使用依赖注入框架(如 Spring, Guice)或工厂模式组装依赖。
  5. 设置架构测试(ArchUnit)验证依赖规则。
// 高层模块定义的契约(属主为调用方)
public interface PaymentProcessor {
    Result process(Order order);
}

// 低层模块实现契约(依赖倒置)
public class StripeProcessor implements PaymentProcessor {
    public Result process(Order order) {
        // 具体实现细节
    }
}
验收项标准检查手段
依赖方向正确性高层模块不直接依赖低层模块的具体类代码审查 / ArchTest
可测试性高层模块可在无低层实现的情况下独立测试单元测试覆盖率
组件独立性替换低层实现不需要修改高层模块模拟替换测试
模块依赖方向拓扑对比 紧耦合架构:正向依赖 高层业务模块 (A) 低层逻辑模块 (B) 依赖流 (实线) 数据流 (虚线) 松耦合架构:反向依赖 (DIP) 高层业务模块 (A) 抽象接口 (契约) 低层实现模块 (B) 依赖流 (实线) 数据流 (虚线)