领域实体方法参数接口的包选型及Ports and adapters架构下的包命名咨询
包命名与接口位置指南(基于Ports & Adapters/DDD)
Great question—this is exactly where Ports & Adapters (Hexagonal Architecture) shines, and getting the package naming right will make your codebase clean and maintainable long-term. Let’s walk through this step by step:
1. 采用Ports & Adapters命名的建议(推荐)
This is the most explicit approach for separating concerns, and it aligns perfectly with your goal of keeping the domain layer independent:
领域层包结构
- 核心领域实体放在
com.yourapp.todo.domain(比如你的Task类) - 把
ToFileSaver接口放在com.yourapp.todo.domain.ports.out- 原因:在Ports & Adapters术语里,这是一个输出端口——它是领域定义的契约,告诉外部系统“我需要你这样来保存我的数据”。领域不关心实现细节,只要求契约被满足。
基础设施层包结构
- 基础设施层根包:
com.yourapp.todo.infrastructure - 实现
ToFileSaver的类(比如FileSystemFileSaver)放在com.yourapp.todo.infrastructure.adapters.out.filesystem- 这样命名能清晰表明这是一个输出适配器:它是把领域的输出端口和具体技术(比如文件系统)连接起来的具体实现。
2. 非Ports & Adapters命名替代方案
如果你偏好更通用的术语(仍符合DDD思想):
- 领域层接口可以放在
com.yourapp.todo.domain.spi(SPI = Service Provider Interface)——这是ports.out的常见替代命名,表达的含义一致:领域对外暴露的、供外部实现的契约。 - 基础设施层实现可以放在
com.yourapp.todo.infrastructure.persistence或com.yourapp.todo.infrastructure.file——只要能明确和领域层分离,且绑定到具体技术即可。
3. 关键:领域实体方法参数的接口位置
ToFileSaver接口必须放在领域层(domain.ports.out或domain.spi),原因如下:
- 你的
Task是领域实体,它应该只依赖领域层的代码。如果把接口放在基础设施层,会形成反向依赖(领域依赖基础设施),这完全违背了分层架构的核心原则。 - 把接口留在领域层,能保持领域的纯粹性:它定义自己的需求,外部系统去适配它,而不是反过来。
示例目录结构
com/ yourapp/ todo/ domain/ Task.java ports/ out/ ToFileSaver.java infrastructure/ adapters/ out/ filesystem/ FileSystemFileSaver.java application/ # 可选:协调领域逻辑与基础设施 TaskService.java
内容的提问来源于stack exchange,提问作者Sampeteq
相关产品推荐
相关产品推荐

