域驱动设计:域服务,应用程序服务

有人可以通过提供一些例子来解释域和应用程序服务之间的区别吗? 而且,如果一个服务是一个域服务,我会把这个服务的实际实现放到域程序集中吗?如果是这样,我是否也会将这个服务注入库注入到这个域服务中? 有些信息会非常有帮助。


服务有三种类型: 域服务应用服务基础设施服务

  • 域服务 :封装不适合域对象的业务逻辑,并且不是典型的CRUD操作 - 这些操作将属于存储库。
  • 应用程序服务 :由外部消费者用来与您的系统通话(思考Web服务)。 如果消费者需要访问CRUD操作,他们就会暴露在这里。
  • 基础设施服务 :用于抽象技术问题(例如MSMQ,电子邮件提供商等)
  • 保持域服务与你的域对象是明智的 - 它们都专注于域逻辑。 是的,您可以将存储库注入您的服务。

    应用程序服务通常会同时使用域服务和存储库来处理外部请求。

    希望有所帮助!


    (如果你不喜欢阅读,底部有一个总结:-)

    我也一直在努力应对服务的确切定义。 尽管Vijay的回答在一个月前对我的思考过程非常有帮助,但我不同意它的一部分。

    其他资源

    关于应用程序服务的信息很少。 诸如聚合根,存储库和域服务之类的主题被广泛讨论,但应用服务仅被简要地提及或完全忽略。

    MSDN杂志文章“领域驱动设计简介”将应用程序服务描述为将域模型转换和/或公开给外部客户端的方式,例如作为WCF服务。 这就是Vijay如何描述应用程序服务。 从这个角度来看,应用程序服务是您的域的一个接口

    Jeffrey Palermo关于洋葱建筑的文章(第一部分,第二部分和第三部分)是一篇很好的文章。 他将应用程序服务视为应用程序级别的概念 ,例如用户会话。 虽然这更接近我对应用服务的理解,但它仍然不符合我对这一主题的想法。

    我的想法

    我已经开始将应用程序服务视为应用程序提供的依赖关系 。 在这种情况下,应用程序可以是桌面应用程序或WCF服务。

    时间为例。 你从你的域名开始。 所有实体和任何不依赖于外部资源的域服务都在这里实现。 任何依赖于外部资源的领域概念都是由一个接口定义的。 这是一个可能的解决方案布局(项目名称以粗体显示):

    My Solution
    - My.Product.Core (My.Product.dll)
      - DomainServices
          IExchangeRateService
        Product
        ProductFactory
        IProductRepository
    

    ProductProductFactory类已在核心程序集中实现。 IProductRepository是可能由数据库支持的东西。 这个实现不是域的问题,因此由接口定义。

    目前,我们将重点介绍IExchangeRateService 。 此服务的业务逻辑由外部Web服务实现。 然而,它的概念仍然是该领域的一部分,并由此界面来表示。

    基础设施

    外部依赖项的实现是应用程序基础结构的一部分:

    My Solution
    + My.Product.Core (My.Product.dll)
    - My.Product.Infrastructure (My.Product.Infrastructure.dll)
      - DomainServices
          XEExchangeRateService
        SqlServerProductRepository
    

    XEExchangeRateService通过与xe.com进行通信XEExchangeRateService实现IExchangeRateService域服务。 通过包含基础架构程序集,您的应用程序可以使用此实现来利用您的域模型。

    应用

    请注意,我还没有提到应用程序服务。 我们现在看看那些。 假设我们想要提供一个IExchangeRateService实现,它使用缓存来快速查找。 这个装饰器类的轮廓看起来像这样。

    public class CachingExchangeRateService : IExchangeRateService
    {
        private IExchangeRateService service;
        private ICache cache;
    
        public CachingExchangeRateService(IExchangeRateService service, ICache cache)
        {
            this.service = service;
            this.cache = cache;
        }
    
        // Implementation that utilizes the provided service and cache.
    }
    

    注意ICache参数? 这个概念不属于我们的域名,所以它不是域名服务。 这是一个应用程序服务 。 这是我们的基础设施的依赖性,可能由应用程序提供。 我们来介绍一个演示这个的应用程序:

    My Solution
    - My.Product.Core (My.Product.dll)
      - DomainServices
          IExchangeRateService
        Product
        ProductFactory
        IProductRepository
    - My.Product.Infrastructure (My.Product.Infrastructure.dll)
      - ApplicationServices
          ICache
      - DomainServices
          CachingExchangeRateService
          XEExchangeRateService
        SqlServerProductRepository
    - My.Product.WcfService (My.Product.WcfService.dll)
      - ApplicationServices
          MemcachedCache
        IMyWcfService.cs
      + MyWcfService.svc
      + Web.config
    

    这一切都像这样应用在一起:

    // Set up all the dependencies and register them in the IoC container.
    var service = new XEExchangeRateService();
    var cache = new MemcachedCache();
    var cachingService = new CachingExchangeRateService(service, cache);
    
    ServiceLocator.For<IExchangeRateService>().Use(cachingService);
    

    概要

    完整的应用程序由三个主要层组成:

  • 基础设施
  • 应用
  • 域层包含域实体和独立域服务。 任何依赖外部资源的域概念(包括域服务,还包括存储库)都由接口定义。

    基础架构层包含来自域层的接口的实现。 这些实现可能会引入必须提供给应用程序的新的非域依赖关系。 这些是应用程序服务,由接口表示。

    应用程序层包含应用程序服务的实现。 如果基础设施层提供的实现不足,应用层还可能包含域接口的其他实现。

    尽管这种观点可能与服务的一般DDD定义不一致,但它确实将域与应用程序分开,并允许您在多个应用程序之间共享域(和基础结构)程序集。


    帮助我了解应用程序服务和域服务之间差异的最佳资源是Eric Evans货运示例的Java实现,可在此处找到。 如果您拒绝加载它,您可以查看RoutingService(域服务)和BookingService,CargoInspectionService(它们是应用程序服务)的内部结构。

    我的'哈哈'时刻是由两件事引发的:

  • 阅读上面链接中关于服务的描述,更确切地说是这句话:
  • 域服务以无处不在的语言和域类型表示,即方法参数和返回值是适当的域类。

  • 阅读这篇博文,特别是这一部分:
  • 我发现在将苹果与橘子分离方面有很大的帮助,这是从应用程序工作流程的角度思考的。 所有有关应用程序工作流程的逻辑通常最终都是将应用程序服务分解到应用程序层中,而来自域的概念似乎不适合作为模型对象最终形成一个或多个域服务。

    链接地址: http://www.djcxy.com/p/26859.html

    上一篇: Domain Driven Design: Domain Service, Application Service

    下一篇: Good Domain Driven Design samples