Interface 在分层体系结构中,在何处定义存储库的接口?

Interface 在分层体系结构中,在何处定义存储库的接口?,interface,domain-driven-design,layer,n-tier-architecture,ddd-repositories,Interface,Domain Driven Design,Layer,N Tier Architecture,Ddd Repositories,背景 我试图创建一个简单的应用程序来真正理解DDD+TDD+等的整个堆栈。我的目标是在运行时动态注入DAL存储库类。这让我的 域和应用程序服务层是可测试的。我计划用“穷人的DI”来完成 现在这个。。。因此,我会在一个简单的控制台应用程序中在接近启动时执行此操作: // Poor man's DI, injecting DAL repository classes at runtime var productRepository = new SimpleOrder.Repository.P

背景

我试图创建一个简单的应用程序来真正理解DDD+TDD+等的整个堆栈。我的目标是在运行时动态注入DAL存储库类。这让我的 域和应用程序服务层是可测试的。我计划用“穷人的DI”来完成 现在这个。。。因此,我会在一个简单的控制台应用程序中在接近启动时执行此操作:

// Poor man's DI, injecting DAL repository classes at runtime var productRepository = new SimpleOrder.Repository.ProductRespository(); var customerRepository = new SimpleOrder.Repository.CustomerRepository(); var orderRepository = new SimpleOrder.Repository.OrderRepository(); // Constructor injection into this class in the Application Services layer, // SimpleOrder.ApplicationFacade OrderEntry oe = new OrderEntry(customerRepository, orderRepository, productRepository); //可怜人的DI,在运行时注入DAL存储库类 var productRepository=new SimpleOrder.Repository.ProductRespository(); var customerRepository=new SimpleOrder.Repository.customerRepository(); var ordererepository=new SimpleOrder.Repository.ordererepository(); //构造函数注入到应用程序服务层的此类中, //SimpleOrder.ApplicationFacade OrderEntry oe=新的OrderEntry(customerRepository、orderRepository、productRepository); 为了完成此依赖项注入,我创建了三个存储库接口:

-- ICustomerRepository -- IOrderRepository -- IProductRespository --ICustomerRepository --IOrderRepository --生产性 一个典型的实现:

namespace SimpleOrder.Domain.Interfaces { public interface ICustomerRepository { Customer GetCustomerById(int customerId); void SaveCustomer(Customer customer); } } 命名空间SimpleOrder.Domain.Interfaces { 公共接口ICCustomerRepository { Customer getcustomerbyd(int customerId); 作废保存客户(客户); } } **请注意,SaveCustomer引用在域层中定义的Customer模型类。这是其他存储库的典型情况

但是我不确定它们应该在哪个项目/层中实现。我在一个解决方案中有5个项目:

  • SimpleOrder.ConsoleClient(演示文稿) --我想从这里将域的具体实现作为应用程序注入

  • SimpleOrder.ApplicationFacade(应用程序服务) --在域中编排较低级别方法的大块的更高级别、粗粒度的方法

  • SimpleOrder.Contracts --用于表示和应用程序服务之间通信的DTO类

  • SimpleOrder.Domain(Domain/bll) --域模型类客户、订单、订单项、产品

  • SimpleOrder.Repository(dal) --实现存储库接口

  • 在我看来,以下是我的选择:

    选项1:在SimpleOrder.Contracts中定义存储库接口

    赞成:这是我认为它们应该属于的地方,因为我创建它是为了在各种关注点/层之间共享契约。例如,这里定义了DTO

    缺点:但是,每个接口中的方法签名引用域模型类。
    这意味着我必须添加对SimpleOrder.Domain的引用,但是当 SimpleOrder.Contracts在另一个项目中引用,它将必须执行 SimpleOrder.Domain随车而去。这感觉不对

    选项2:与上述场景相同,但我也为每个域模型定义了接口 在SimpleOrder.Contracts中初始化,这样我就可以打破存储库接口与实际模型类的耦合

    例如:

    namespace SimpleOrder.Domain.Interfaces { public interface ICustomerRepository { ICustomer** GetCustomerById(int customerId); void SaveCustomer(ICustomer customer); } public interface ICustomer { int CustomerId { get; set; } string Name { get; set; } System.Collections.Generic.List Orders { get; } } } 命名空间SimpleOrder.Domain.Interfaces { 公共接口ICCustomerRepository { iccustomer**getcustomerbyd(int customerId); 作废保存客户(ICustomer客户); } 公共接口ICustomer { int CustomerId{get;set;} 字符串名称{get;set;} System.Collections.Generic.List订单{get;} } } 影响:每个域模型类都必须实现其相关接口。i、 e

    public class Customer : SimpleOrder.Domain.Interfaces.ICustomer { public Customer() { _orders = new List(); } public int CustomerId { get; set; } public string Name { get; set; } private List _orders; public virtual List Orders { get { return _orders; } } } 公共类客户:SimpleOrder.Domain.Interfaces.iccustomer { 公众客户() { _订单=新列表(); } public int CustomerId{get;set;} 公共字符串名称{get;set;} 私人名单(订单);; 公共虚拟列表命令{ 获取{返回_订单;} } } 赞成:修复选项1的问题

    缺点:这会爆炸项目中的文件数量(以及感知的复杂性),因为 每个域类现在都有一个关联的接口

    选项3:在SimpleOrder.Domain中定义存储库接口

    影响:为了在运行时从SimpleOrder.ConsoleClient向应用程序服务层(SimpleOrder.ApplicationFacade项目)注入具体的存储库类,SimpleOrder.ConsoleClient还需要对SimpleOrder.Domain的引用

    赞成:这也解决了选项1

    缺点:我试图避免直接从表示层引用域层,因为现在表示层对域层的了解太多了。当我将来用WPF或ASP.NET MVC应用程序替换控制台应用程序时,我会冒着第二层和后续表示层实现尝试调用模型中的方法而不是应用程序服务层的风险。(但我在选择4中考虑这个问题)

    选项4:将接口放入SimpleOrder.Domain,然后从SimpleOrder.ConsoleClient引用SimpleOrder.Domain

    PRO:修复了上述所有问题

    缺点:这感觉不对,因为我会提供来自表示层的访问 当我只应该提供 访问SimpleOrder.ApplicationFacade中更高级别的chunky方法

    问题
    我已经尝试了每一种方法,但是选择了第四种方法,但是这让我的口碑不好。有更好的选择吗?我在这方面做得对吗?

    根据我对你问题的理解,我同意选择4是最好的。存储库接口应该在域层中的所有