关于构造域驱动设计命名空间的一些问题

Pet*_*ter 10 c# api design-patterns domain-driven-design namespaces

我对框架设计有一些一般性的问题.

我正在使用C#.NET(框架3.5)和SQL 2008(使用LINQ)为iPhone应用程序构建API.我遵循了Domain-Driven-Design模式(在一本书中)并具有以下文件夹结构:

Core
- DataAccess
--Impl
-Domain
-Impl
Run Code Online (Sandbox Code Playgroud)

Core是我的核心API库 - 我的DLL.DataAccess包含数据访问接口DataAccess.Impl包含存储库(LINQ to the DB)Domain包含我的大部分数据类型和属性.Impl包含我的服务(即AccountService.cs,EmailService.cs)

现在,作为练习,我已经为此项目添加了一个Windows服务,并尝试从此服务中的DLL调用功能.我的问题是,我应该将哪一层暴露给其他应用程序以及应该隐藏什么?

  • Impl文件夹中的服务类应该是程序员看到的吗?
  • 或者来自DataAccess.Impl的存储库?
  • 或者,我应该全力以赴让程序员看到吗?从现在看来,这似乎有点令人困惑.

当我开始阅读DDD时,我假设存储库将被服务类隐藏和访问,但我发现我需要在客户端调用两者的功能.我设计错了吗?

我的另一个问题是命名空间命名.当Windows服务从我的核心库调用功能时,我必须这样做我的包括:

using Company.Product.ProductCore.Core.DataAccess.Impl 
using Company.Product.ProductCore.Core.Domain 
using Company.Product.ProductCore.Core.Impl
Run Code Online (Sandbox Code Playgroud)

这看起来很罗嗦.看看微软的DLL,他们似乎遵循两层约定 - (System.Linq,System.Text等).让Company.Product.ProductCore.Core.Impl看起来很乱,并没有真正告诉程序员这个命名空间做了什么(但它是我读过的例子所建议的).这里有最好的做法吗?

您的建议(以及任何示例)都非常感谢.

谢谢.

Wil*_*ler 7

在我看来,域名绝对不是您想要的,也不是您的数据访问层.

在我的愚见,有什么就不得不暴露尚不存在,那就是,一个静态类,让我们说,如果我们考虑的门面设计模式,这暴露你的库子系统的特性和功能.

替代文字

外墙设计模式解释:

  1. 外墙设计 - 模式 - (四人帮) ;
  2. 门面图案(维基百科).

那么最后,你的代码应该做什么?只需暴露您应该知道的必要内容,因为您是唯一了解您正在开发的系统的人.

简而言之,我经常使用Façade模式,这样我就可以在幕墙的引擎下隔离我的类,实现和几个相关的子系统.让我们考虑一下我们是一个全新的汽车经销商.这个外观将是伟大的窗户,让您看到在展示厅暴露的汽车.你必须想到这个外观所暴露的东西.它只暴露汽车吗?

在我看来,这种外观暴露出汽车,您将能够购买,借钱买的,修理汽车,购买其他相关配件等配件,然后被曝光,但只需要什么.与汽车等其他项目相同.也就是说,您可能希望只公开接口,并保留实施自己,好让通过你的门面,当你必须返回一个ICarIAccessory,你必须通过你的实现对象类实例化它们,然后通过你的façade返回接口实例.这就是说,用户并不需要知道什么是引擎盖下回事,但只有当他想要一辆车,他要通过你的门面订购.就像你不会去梅赛德斯奔驰购买马自达3.你会使用正确的外观.然后,不同的汽车经销商可能只是子系统,因此是某种工厂.然后你问车的外观有这样那样的规格和外观应该知道ICar返回实例来换取你要求它为你提供什么.

希望无论如何这有帮助!=)


Mar*_*ijn 7

如果我没弄错的话,你会问两个问题:

  1. 如何构建DDD应用程序?
  2. 那些长命名空间名称怎么样?

我的回答相当冗长 - 我冒昧地把它分成两个回答者.

这是第二个问题的答案:

那些长命名空间名称怎么样?

我不认为长命名空间名称必然是混乱的.恕我直言,你的名字看起来很乱:

  • 重复"产品"和"核心"
  • 使用通用术语"Impl"

第一个改进可能是:

// The Domain objects go here;
MyCompany.MyProduct.Core.Domain;  
// DataAccess interfaces go here:
MyCompany.MyProduct.Core.DataAccess;
// a Linq implementation of the DataAcces interfaces go here:
MyCompany.MyProduct.Core.DataAccess.LinqImpl; 
// The Core service go here:
MyCompany.MyProduct.Core.Services;
// Some general purpose infrastructure goes here (e.g. emailing code)
Mycompany.MyProduct.Infra;
Run Code Online (Sandbox Code Playgroud)

此外,我发现在代码结构中使用商业产品名称(例如MyProduct)是不好的(如果营销选择不同的名称会怎么样?); 我喜欢使用逻辑子系统的名称.让我们假设您的建筑汽车租赁系统.然后CarRental将被视为此应用程序的核心功能.然后我使用以下命名空间结构(Serra是我公司的名称):

// For classes Customer, Account, Car
Serra.CarRental.Domain;    
// I use Dao as a general abbreviation for "Data Access Objects"
// Dao interfaces go here:
Serra.CarRental.Dao;     
// Linq implementation for Dao interfaces  
Serra.CarRental.Dao.Linq;
// For Services specific to the car rental domain: 
// AccountService and RentalService and CarAvailabilityService
Serra.CarRental.Services;  
// For UI objects (not relevant in you situation?)
Serra.CarRental.UI;
// general service code; ignorant of the CarRental domain (e.g. an EmailService)
Serra.Infra.Service;       
Run Code Online (Sandbox Code Playgroud)