Domain driven design DDD存储库中的过滤器

Domain driven design DDD存储库中的过滤器,domain-driven-design,Domain Driven Design,有一个活动实体,为此,我有一个具有此功能的活动存储库 公共IList FindAll() 公共活动FindByCampaignNumber(字符串编号) 但现在我想要这个标准-: 查找今天创建的活动 查找本月创建的活动 查找最新的前5个活动 查找今年创建的活动 所以对于所有这些活动过滤器 我是否在存储库中为它们中的每一个创建单独的函数? 并以这种方式实施 获取所有活动,然后筛选所需的活动,但我不想要所有活动。在谷歌搜索时,我发现这个解决方案 1: 有什么方法可以避免使用多个函数,还是继续为每个过

有一个活动实体,为此,我有一个具有此功能的活动存储库

  • 公共IList FindAll()
  • 公共活动FindByCampaignNumber(字符串编号) 但现在我想要这个标准-:

  • 查找今天创建的活动
  • 查找本月创建的活动
  • 查找最新的前5个活动
  • 查找今年创建的活动
  • 所以对于所有这些活动过滤器

    我是否在存储库中为它们中的每一个创建单独的函数?

    并以这种方式实施

    获取所有活动,然后筛选所需的活动,但我不想要所有活动。在谷歌搜索时,我发现这个解决方案

    1:


    有什么方法可以避免使用多个函数,还是继续为每个过滤器创建单独的函数?

    您考虑过在应用程序中实现模式吗?也许这看起来有些过分,但如果你的应用程序有一些复杂的用户过滤选项,它可能会被证明是有用的

    class CampaignSpecification
    {
        public CampaignSpecification Number(string number);
        public CampaignSpecification DateBetween(DateTime from, date to);
        public CampaignSpecification Year(DateTime year);
    } //I have omitted all the AND/OR stuff it can be easily implemented with any SQL like query language
    
    下面是一个从存储库加载的示例

    var  campaignList = CampaignRepository.load(
                new CampaignSpec()
                    .Number("2")
                    .Year(DateTime.Now);
    
    我还想补充一点,这在很大程度上取决于您使用的是哪种数据访问解决方案,当您知道将使用哪种API(标准API、SQL或其他什么)时,它会使实现更容易,因此您可以调整您的规范接口,使其实现更简单


    更新:如果您使用linq和nHibernate在.NET中实现规范,请查看

    我将创建两个规范:TopActivitySpec和CampaingCreatedSpec

    var spec = CampaignCreatedSpec.ThisYear();
    var campaigns = CampaignsRepository.FindSatisfying(spec);
    
    如果您在其他地方需要此功能,也可以用更通用的DateRange类替换CampaingCreatedSpec:

    var thisYear = DateRange.ThisYear();
    var campaigns = CampaignsRepository.FindByDateRange(spec);
    
    我还强烈建议远离“通用”存储库和实体。请阅读

    从DDD的角度来看,数据访问代码是否实现为SQL/HQL/ICriteria,甚至是web服务调用都无关紧要。此代码属于存储库实现(数据访问层)。这只是一个示例:

    public IList<Campaign> FindByDateRange(CampaignCreatedSpec spec) {
        ICriteria c = _nhibernateSession.CreateCriteria(typeof(Campaign));
        c.Add(Restrictions.Between("_creationDate", spec.StartDate, spec.EndDate));
        return c.List<Campaign>();
    }
    
    public IList FindByDateRange(活动创建规范){
    ICriteria c=_nhibernateSession.CreateCriteria(typeof(Campaign));
    c、 添加(限制介于(“_creationDate”,spec.StartDate,spec.EndDate));
    返回c.List();
    }
    
    您应该能够使用以下存储库方法执行上述所有操作:

    List<Campaign> findCampaigns(Date fromCreationDate, Date toCreationDate, int offset, Integer limit) {
    
       if (fromCreationDate != null) add criteria...
       if (toCreationDate != null) add criteria...
       if (limit != null) add limit...
    }
    
    列出查找的示例(日期从CreationDate、日期到CreationDate、整数偏移量、整数限制){
    如果(fromCreationDate!=null)添加条件。。。
    如果(toCreationDate!=null)添加条件。。。
    如果(限制!=null)添加限制。。。
    }
    

    我就是这样做的,而且效果很好。

    以下是我将如何做到这一点:

    class Campaigns{
      IEnumerable<Campaign> All(){...}
      IEnumerable<Campaign> ByNumber(int number){...}
      IEnumerable<Campaign> CreatedToday(){...}
      IEnumerable<Campaign> CreatedThisMonth(){...}
      IEnumerable<Campaign> CreatedThisYear(){...}
      IEnumerable<Campaign> Latest5(){...}
    
      private IQueryable<Campaign> GetSomething(Something something){
        //used by public methods to dry out repository
      }
    }
    
    班级活动{
    IEnumerable All(){…}
    IEnumerable ByNumber(整数){…}
    IEnumerable CreatedToday(){…}
    IEnumerable CreatedThisMonth(){…}
    IEnumerable CreatedThisYear(){…}
    IEnumerable Latest5(){…}
    私人IQueryable获取某物(某物){
    //由公共方法用于干燥存储库
    }
    }
    
    推理很简单——它取决于你对寻找活动感兴趣的内容(知识是你领域的一部分)。如果我们显式地声明函数来反映这一点,我们将始终知道它



    在活动存储库中添加所有这些方法是否合适

    我看不出有什么问题


    Arnis我想要一些代码,你是如何在域中实现CreatedToday函数的,你是在这个函数中注入存储库的吗?谢谢你的合作


    我不会在我的域中实现CreatedToday函数。它将位于存储库中,存储库实现不应该是域的问题。如果您的意思是我将如何使用活动存储库,如果它应该从域中使用-不,它不应该从域中使用。如果您的意思是,如果我将存储库插入存储库中,您会听到太多。

    如果我使用此解决方案,那么继续使用上面给出的链接第二个链接会更好,因为它显示了方法链接部分,回答您的问题:)当然,这取决于您的决定。还有签出和如何实现规范。我是否提取所有活动,然后在其上循环,然后对每个实体应用规范。这是正确的。如果我使用这个解决方案,russelleast.wordpress.com/2008/09/20/…–kamal 1分钟前编辑并继续上面给出的链接我是在存储库中为两个规范创建两个方法,还是在应用层创建它,获取所有活动,然后在那里应用规范?在存储库中创建两个方法。规范是模型/业务逻辑层的一部分。但是,基于此规范获取数据是数据访问层(您的存储库实现)的责任。dmitry您告诉我将规范转换为hql或nhibernate标准,我不知道如何做。你有任何代码或链接。同时,我正在应用这样的规范。好的,我也想到了你的方法,但是现在假设我的条件增加了,那么我应该在findcampaigns方法中添加更多的参数,还是分离出另一个方法。是的,你只需要添加更多的参数。但是请记住,如果您使用另一种建议的方法,您几乎可以直接使用JPQL/JPA criteria API,另外,如果您正在进行集成测试,那么使用过于灵活的find方法将使测试变得非常困难。好的,同样的原则也适用。通过创建某种动态过滤,您将使自己的生活变得非常困难。测试将很困难,等等@Piotr:参数列表很长是众所周知的代码味道。它很难阅读、理解、测试等。不要向任何人建议。@Piotr:4已经达到极限。您建议“是的,您只需添加更多参数”。这尤其糟糕,因为在某些情况下应该忽略某些参数。添加一个