You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

领域驱动设计:领域层仓库接口用DTO作查询过滤器是否合规?

领域层Repository接口:过滤器对象 vs 分散传参

根据Eric Evans在《领域驱动设计》中的核心指导,判断方案是否合规的关键在于是否贴合领域概念的封装与内聚,而非教条地排斥某种形式。针对你的问题,具体分析如下:

1. 优先选择封装参数(但别用"DTO"这个术语)

你的示例方法签名有5个参数,冗长且缺乏内聚性——这恰恰是DDD要解决的"代码散化"问题。Evans强调领域层应当围绕有意义的领域概念组织代码,所以:

  • 如果这些参数组合对应业务中一个明确的查询场景(比如"有效样本查询条件"、"特定时间段样本筛选规则"),直接把它封装成领域值对象(Value Object)。比如定义SampleSearchCriteria,把参数校验、默认值设置等逻辑封装在对象内部,让Repository接口依赖这个领域对象,而非零散参数。
  • 如果只是临时的参数聚合(无明确业务名称),也可以在领域层定义一个简单的查询参数对象,但别叫它DTO——DTO本质是跨层传输的数据容器,而领域层的参数对象是为了内聚领域查询逻辑,属于领域层的一部分。

示例重构后的接口:

public interface ISampleRepository
{
    Task<IEnumerable<Sample>> FindByCriteriaAsync(SampleSearchCriteria criteria, CancellationToken cancellationToken);
}

// 领域层的查询条件值对象
public record SampleSearchCriteria(int Param1, int Param2, string Param3, DateTime Param4, int Param5)
{
    // 可选:添加领域规则校验,比如Param1不能为负数
    public static SampleSearchCriteria Create(int param1, int param2, string param3, DateTime param4, int param5)
    {
        if (param1 < 0)
            throw new DomainException("Param1不能为负数");
        return new SampleSearchCriteria(param1, param2, param3, param4, param5);
    }
}

2. 为什么分散传参不是好选择?

Evans在书中反复强调"保持领域模型的清晰度",分散传参的问题在于:

  • 方法签名冗长,可读性差,调用方需要记忆一堆无关联的参数;
  • 新增或修改参数时,必须修改Repository接口及所有实现、调用方,违反开闭原则;
  • 无法封装与查询相关的领域规则(比如参数之间的约束关系),导致逻辑散落在调用方,破坏领域层的内聚性。

3. 关于"领域层引入DTO是否违反纯领域原则"?

如果你说的DTO是应用层或基础设施层的传输对象,那确实不合适——领域层不应依赖外部层的对象,否则会打破六边形架构的边界(领域层是核心,外部层依赖领域层)。但如果是领域层自己定义的参数对象(哪怕结构简单),这完全符合纯领域原则,因为它是为了服务领域查询逻辑而存在的。

总结

依据Eric Evans的指导,最佳方案是:将零散参数封装为领域层内的查询参数对象(优先做成值对象)。这样既解决了方法签名冗长的问题,又保持了领域层的内聚性与纯领域原则,同时契合六边形架构中领域层作为核心的设计思想。

内容的提问来源于stack exchange,提问作者Gabriel Ribeiro

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 11:05:02