【发布时间】:2012-11-30 12:54:34
【问题描述】:
背景
我正在尝试创建一个简单的应用程序来真正了解 DDD+TDD+等的整个堆栈。我的目标是在运行时动态注入 DAL 存储库类。这让我的 域和应用服务层可测试。我打算用“穷人的DI”来完成 这个暂时...所以我会在启动时在一个简单的控制台应用程序中执行此操作:
// 可怜人的 DI,在运行时注入 DAL 存储库类 var productRepository = new SimpleOrder.Repository.ProductRespository(); var customerRepository = new SimpleOrder.Repository.CustomerRepository(); var orderRepository = new SimpleOrder.Repository.OrderRepository(); // 在应用服务层将构造函数注入到这个类中, // SimpleOrder.ApplicationFacade OrderEntry oe = new OrderEntry(customerRepository, orderRepository, productRepository);为了完成这种依赖注入,我创建了三个存储库接口:
-- ICustomerRepository -- IOrderRepository -- IProductRespository一个典型的实现:
命名空间 SimpleOrder.Domain.Interfaces { 公共接口 ICustomerRepository { 客户 GetCustomerById(int customerId); 无效 SaveCustomer(客户客户); } }** 请注意,SaveCustomer 引用了域层中定义的 Customer 模型类。这是其他存储库的典型特征。
但是我不确定它们应该在哪个项目/层中实现。我在一个解决方案中有 5 个项目:
SimpleOrder.ConsoleClient(演示文稿) -- 我想从这里作为应用程序注入域的具体实现
SimpleOrder.ApplicationFacade(应用程序服务) -- 在域中编排低级方法的大块高级、粗粒度方法
SimpleOrder.Contracts -- DTO 类用于表示和应用程序服务之间的通信
SimpleOrder.Domain(域/bll) -- 领域模型类 Customer、Order、OrderItem、Product
SimpleOrder.Repository (dal) -- 实现存储库接口
这是我看到的选项:
选项 1: 在 SimpleOrder.Contracts 中定义存储库接口 ...
PRO:这是我认为他们应该属于的地方,因为我创建它是为了在各个关注点/层之间共享合同。例如,这里定义了 DTO。
CON:但是每个接口的方法签名都引用了域模型类。
这意味着我必须添加对 SimpleOrder.Domain 的引用,但是当
SimpleOrder.Contracts 在另一个项目中被引用,它必须携带
SimpleOrder.Domain 一路顺风顺水。这感觉不对。
选项 2: 与上述相同的场景,但我也为每个域模型定义接口 SimpleOrder.Contracts 中的类,这样我就可以打破存储库接口与实际模型类的耦合。
例子:
命名空间 SimpleOrder.Domain.Interfaces { 公共接口 ICustomerRepository { ICustomer** GetCustomerById(int customerId); 无效 SaveCustomer(ICustomer 客户); } 公共接口 ICustomer { int 客户 ID { 获取;放; } 字符串名称 { 获取;放; } System.Collections.Generic.List Orders { get; } } }影响:每个领域模型类都必须实现其相关接口。即,
公共类客户:SimpleOrder.Domain.Interfaces.ICustomer { 公共客户() { _orders = 新列表(); } 公共 int CustomerId { 获取;放; } 公共字符串名称 { 获取;放; } 私有列表_orders; 公共虚拟列表订单{ 得到{返回_orders; } } }专业版:修复选项 1 的问题。
CON:这会增加项目中的文件数量(以及感知的复杂性),因为 现在每个域类都有一个关联的接口。
选项 3: 在 SimpleOrder.Domain 中定义存储库接口
影响:为了在运行时将具体的存储库类从 SimpleOrder.ConsoleClient 注入应用程序服务层(SimpleOrder.ApplicationFacade 项目),SimpleOder.ConsoleClient 还需要对 SimpleOrder.Domain 的引用。
PRO:这也解决了选项 1
CON:我试图避免直接从表示层引用领域层,因为现在表示层可以对领域层了解太多。当我将来用 WPF 或 ASP.NET MVC 应用程序替换控制台应用程序时,我会冒第二个和后续表示层实现尝试调用模型而不是应用程序服务层中的方法的风险。 (但我确实在选项 4 中考虑了这一点。)
选项 4: 将接口放入 SimpleOrder.Domain,然后从 SimpleOrder.ConsoleClient 引用 SimpleOrder.Domain。
专业版:修复以上所有问题。
CON:这感觉不对,因为我会从表示层提供访问权限 当我应该只提供时,直接到域层中的较低级别的方法 访问 SimpleOrder.ApplicationFacade 中更高级别的 chunky 方法。
问题 我已经尝试了其中的每一个,但已经选择了选项 4,但是这在我的嘴里留下了不好的味道。有更好的选择吗?我在正确的轨道上吗?
【问题讨论】:
-
仔细检查...选项 3 和 4 基本相同。哎呀。我应该更仔细地校对。
标签: interface domain-driven-design layer n-tier-architecture ddd-repositories