模块描述文件是架构治理的“契约文本”,须在编译期和构建期强制执行分层与隔离,通过显式声明依赖与导出规则(如Java module-info.java、Go go.mod)、配合工具链(ArchUnit、jdeps、Clang AST)自动化验证,实现设计意图的机器可读、可验证与落地。

模块描述文件是架构治理的“契约文本”,不是可有可无的配置,而是编译期和构建期强制执行分层与隔离的依据。它把设计意图固化为机器可读、可验证的规则,让规范真正落地,而不是停留在文档或Code Review里。
用模块描述定义清晰的层边界
在 Java(JPMS)、Go 或支持模块系统的 C++20 项目中,模块描述文件(如 module-info.java、go.mod、module interface unit)必须显式声明“谁可以被谁看到”。这不是装饰,是访问控制的开关。
- 业务逻辑层模块只 exports 接口包(如
com.example.order.api),绝不导出impl或internal包 - 数据访问层模块 requires 数据库驱动,但不 requires 任何 Web 层或 UI 模块
- Web 层模块可 requires 业务逻辑层,但禁止反向依赖;构建时通过工具(如 ArchUnit、jdeps)自动检测并报错循环引用
通过描述文件约束变量与符号可见性
变量隔离本质是作用域控制。模块描述文件配合语言机制,能从源头切断非法访问。
- C++20 模块中,未 export 的函数、类型、全局变量默认不可见;即使同名,不同模块内的
static int counter也互不影响 - Go 模块中,小写首字母的变量/函数天然包级私有;go.mod 确保外部无法直接 import 内部目录(如
example.com/order/internal/db) - Java 中,模块未 opens 的包,连反射都无法访问其私有成员——这比
private更彻底
把描述文件变成构建流水线中的守门人
模块描述本身不执行检查,必须集成进 CI/CD 才能生效。关键在于自动化验证。
- 在 Maven 构建中,用
maven-enforcer-plugin+ 自定义规则校验module-info.java是否遗漏requires或错误导出内部包 - 用 ArchUnit 编写测试:断言“所有 controller 类不得 new service 实现类”,失败则阻断构建
- 在 C++ 项目中,将 Clang AST 分析脚本接入 CMake,扫描
import语句,禁止跨层导入(如禁止 presentation 模块import data_access)
配套策略:命名+目录+工具链三位一体
单靠描述文件不够,需结构化支撑:
- 目录严格按层命名:
/src/main/java/com/example/web、/service、/infrastructure,并与模块名对齐(com.example.web模块只含 web 目录代码) - 禁止在头文件(.h)或接口文件中暴露实现细节变量;C 语言中坚持
extern声明 +static定义分离原则 - 用 IDE 插件(如 IntelliJ 的 Module Dependencies Inspector)实时高亮违规依赖,开发阶段就拦截

















