【问题标题】:DDD: Where to keep domain Interfaces, the Infrastructure?DDD:在哪里保留域接口,基础设施?
【发布时间】:2010-10-16 03:30:35
【问题描述】:

将领域层的所有接口(模块、模型、实体、领域服务等)全部归入基础设施层是否有意义?如果没有,创建一个“共享”项目/组件将所有这些组合到一个共享库中是否有意义?毕竟,“基础设施层”的定义包括“域、应用程序和 UI 层的共享库”。

我正在考虑围绕 DDD 层设计我的代码库:UI、应用程序、域、基础架构。这将创建 4 个项目。我的意思是,您从域层引用基础设施层。但是,如果您在域层项目中定义接口,例如 IPost,那么当您在定义 IPostRepository.Save(IPost post) 方法时必须从基础设施项目中引用域层项目时,您将有一个循环引用.因此,“在共享库中定义所有接口”的想法。

也许存储库不应该期望保存对象 (IPostRepository.Save(IPost post); 而是期望对象的参数(尽管这可能是 Save() 中的一长组参数)。鉴于,这可能是一个理想的情况,它显示了对象何时变得过于复杂,应该为它寻找额外的值对象。

想法?

【问题讨论】:

    标签: domain-driven-design


    【解决方案1】:

    关于将存储库放在哪里,我个人总是将存储库放在专用的基础架构层(例如 MyApp.Data.Oracle)中,但在域层中声明存储库必须符合的接口。
    在我的项目中,应用层必须访问域和基础设施层,因为它负责配置域和基础设施层。
    应用层负责将适当的基础设施注入到域中。域不知道它正在与哪个基础设施通信,它只知道如何调用它。当然,我使用诸如 Structuremap 之类的 IOC 容器将依赖项注入到域中。 同样,我并没有说这是 DDD 推荐的构建项目的方式,这只是我构建应用程序的方式。 干杯。

    【讨论】:

    • 优秀的 Geobarteam。那只是给了我一个“呃”的时刻。是的,在域中定义接口,存储库应该在单独的程序集中(MySqlProviver、MsSqlProvider、XmlProvider 等)实现。并且某种类型的 IOC 容器(我喜欢的温莎城堡)用于在应用层连接它。完美。
    • 在 ASP.NET MVC 的情况下,通过 Castle Windosr 将存储库注入控制器(UI 层)实际上很容易。 Steven Sanderson 在 ASP.NET MVC Framework Preview 中有一个很好的例子。我的 Domain-Driven Design Quickly 这本书说 UI、App 和 Domain 都可以使用 Infra。
    • 我唯一的问题是我的书说基础设施从不引用任何东西。 UI-> 应用程序、域和基础设施。应用程序-> 域和基础设施。并且,域-> 基础设施。我知道我知道,无论如何这都应该是指导方针。
    • 我相信围绕“应用程序层负责将适当的基础架构注入域。”的答案存在问题。 Onion 架构告诉我们,基础设施甚至不应该进入域层,例如,它不应该知道必须发送电子邮件的任何事情。我的意思是它不应该知道电子邮件甚至需要发送,而不仅仅是它不知道电子邮件已发送。原因是我们正在尝试编写一个只有核心业务逻辑的纯核心域。更喜欢发送电子邮件作为副作用稀释域。
    【解决方案2】:

    我是 DDD 的新手,所以如果您不同意,请随时发表评论,因为我是来学习的。

    我个人不明白为什么你应该从你的域中引用基础设施层。在我看来,域不应该依赖于基础设施。域对象应该完全不知道它们在哪个数据库上运行或使用哪种类型的邮件服务器来发送邮件。通过从基础设施中抽象领域,更容易重用;因为域不知道它在哪个基础设施上运行。

    我在我的代码中所做的是从我的基础设施层引用域层(但不是相反)。存储库知道域对象,因为它们的作用是保存域的状态。我的存储库包含我的根聚合(get(id)、getall()、save(object)、delete(object) 的基本 CRUD 操作,并从我的控制器中调用。

    我在上一个项目中所做的(我的方法不是纯粹的 DDD,但效果很好)是我用接口抽象了我的存储库。根聚合必须通过传递具体类型的 Repository 来实例化:

    必须使用存储库的 Get(ID) 或 Create() 方法通过存储库实例化根聚合。构造对象的具体存储库通过自身传递,以便聚合可以保留他的状态和他的子对象的状态,但不知道存储库的具体实现。 例如:

    public class PostRepository:IPostRepository
    {
         ...
        public Post Create()
        {
            Post post=new Post(this);
            dbContext.PostTable.Insert(post);
            return post;
         }
         public  Save(post)
         {
             Post exitingPost=GetPost(post.ID);
             existingPost = post;
             dbContext.SubmitChanges();
         }
    }
    
    public class Post
    {
    
         private IPostRepository _repository
         internal  Post(IPostRepository repository)
         {
            _repository = repository;
         }
         ...
        Public Save()
        {
            _repository.Save(this);
         }
    
    }
    

    【讨论】:

    • 我知道你要去哪里。只是在我的 DDD 书中,提到存储库位于基础架构层中。但我在网上找到的相互矛盾的信息将存储库置于域层中。
    • 还提倡UI-Layer访问“Application、Domain、Infrastructure”,Application-Layer访问“Domain and Infrastructure”,Domain-Layer访问“Infrastructure” ”。这来自“快速领域驱动设计”一书。那么,这是什么原因呢?
    • 这是很难确定的信息。我认为我发现存储库的接口进入域层,因为它们为域定义了“接缝”。存储库的“实现”位于基础设施层。想象一下,决定从当前应用程序上下文中完全提取您的域并构建一个全新的域。您需要存储库的接口,但不一定需要实现。跨度>
    【解决方案3】:

    我建议您考虑Onion architecture。它非常适合 DDD。这个想法是,您的存储库接口位于 Domain 外部的一层并直接引用实体:

    IPostRepository.Save(Post post)

    域根本不需要了解存储库。

    Domain 或其他任何人都不会引用基础设施层,它包含存储库的具体实现以及其他与 I/O 相关的内容。在这种情况下,具有各种帮助程序的公共库称为 Application Core,任何人都可以引用它。

    【讨论】:

    • 错了。域存储库和网关接口。基础设施“层”实现它们。
    猜你喜欢
    • 2014-08-17
    • 1970-01-01
    • 2021-01-08
    • 1970-01-01
    • 1970-01-01
    • 2010-11-25
    • 2018-07-03
    • 1970-01-01
    • 2011-11-28
    相关资源
    最近更新 更多