33

我已经开始学习 DDD 并且想知道其他人是如何组织他们的项目的。

我开始围绕我的 AggregateRoots 进行组织:

MyApp.Domain(域模型的命名空间)

MyApp.Domain.Product
- 产品
- IProductService
- IProductRepository
- 等

MyApp.Domain.Comment
- 评论
- ICommentService
- ICommentRepository
- 等

MyApp.Infrastructure
- ...

MyApp.Repositories
- ProductRepository : IProductRepository
- 等等

我遇到的问题是我必须将我的域产品引用为 MyApp.Domain.Product.Product 或 Product.Product。我还与产品的 linq 数据模型发生冲突......我必须使用丑陋的代码行来区分两者,例如 MyApp.Domain.Product.Product 和 MyApp.Respoitories.Product。

我真的很想看看其他人如何组织他们的 DDD 解决方案......

我使用 Visual Studio 作为我的 IDE。

非常感谢。

4

5 回答 5

23

我尽量让事情变得非常简单,所以通常这样的事情对我有用:

Myapp.Domain - 所有特定于域的类共享这个命名空间

Myapp.Data - 将数据库从域中抽象出来的薄层。

Myapp.Application - 所有“支持代码”、日志记录、共享实用程序代码、服务消费者等

Myapp.Web - 网络用户界面

所以类将是例如:

  • Myapp.Domain.Sales.Order
  • Myapp.Domain.Sales.Customer
  • Myapp.Domain.Pricelist
  • Myapp.Data.OrderManager
  • Myapp.Data.CustomerManager
  • Myapp.Application.Utils
  • Myapp.Application.CacheTools

等等。

我尝试记住的想法是“域”命名空间是捕获应用程序实际逻辑的东西。因此,您可以与“领域专家”(将使用该应用程序的家伙)谈论什么。如果我因为他们提到的东西而编码某些东西,它应该在域命名空间中,并且每当我编写他们没有提到的东西(如日志记录、跟踪错误等)时,它不应该在域命名空间中。

因此,我也对制作过于复杂的对象层次结构持谨慎态度。理想情况下,非编码人员应该可以直观地理解域模型的稍微简化的绘图。

为此,我通常不会从详细考虑模式开始。我尝试按照标准的面向对象设计指南尽可能简单地对域进行建模。什么需要成为对象?它们有什么关系?

在我看来,DDD 是关于处理复杂的软件,但如果你的软件本身不是很复杂,那么你很容易陷入这样一种情况,即 DDD 的做事方式增加了而不是消除了复杂性。

一旦您的模型具有一定程度的复杂性,您将开始了解应如何组织某些事物,然后您将知道要使用哪些模式,哪些类是聚合等。

在我的示例中,Myapp.Domain.Sales.Order 将是一个聚合根,因为当它被实例化时,它可能包含其他对象,例如客户对象和订单行集合,并且您只能访问订单行通过 order 对象获取该特定订单。

但是,为了简单起见,我不会有一个“主”对象,它只包含其他所有内容并且没有其他用途,因此订单类本身将具有在应用程序中有用的值和属性。

因此,我将参考以下内容:

Myapp.Domain.Sales.Order.TotalCost

Myapp.Domain.Sales.Order.OrderDate

Myapp.Domain.Sales.Order.Customer.PreferredInvoiceMethod

Myapp.Domain.Sales.Order.Customer.Address.Zip

等等

于 2009-02-09T15:43:38.700 回答
5

我喜欢在应用程序的根命名空间中拥有域,在它自己的程序集中:

Acme.Core.dll[根命名空间:Acme]

这巧妙地代表了域在应用程序所有其他部分的范围内的事实。(有关更多信息,请参阅Jeffrey Palermo的 The Onion Architecture)。

接下来,我有一个将域对象映射到数据库的数据程序集(通常使用NHibernate )。这一层实现了存储库和服务接口:

Acme.Data.dll[根命名空间:Acme.Data]

然后,我有一个演示程序集,声明了我选择的 UI 模式的元素:

Acme.Presentation.dll[根命名空间:Acme.Presentation]

最后是 UI 项目(假设这里有一个 Web 应用程序)。这是前面层中元素的组合发生的地方:

Acme.Web[根命名空间:Acme.Web]

于 2009-02-11T00:27:11.810 回答
3

尽管您也是 .Net 开发人员,但Eric Evans 和 Citerus 的 DDD中货物应用程序的 Java 实现参考是一个很好的资源。

在 doc'd 代码中,您可以在 Java 包中看到 DDD 组织到有界上下文和正在运行的聚合。

此外,您可以考虑 Billy McCafferty 的Sharp Architecture。它是一个 ASP.Net MVC、NHibernate/Fluent NHibernate 实现,它在构建时考虑了 DDD。

诚然,您仍然需要应用文件夹/命名空间解决方案来提供上下文。但是,将 Evans 方法与#Arch 结合起来,您应该会顺利进行。

让我们知道你要做什么。我也在同一条路上,而且离你不远!

快乐编码,

库尔特·约翰逊

于 2009-03-12T15:03:44.490 回答
1

您的域可能有一个名称,因此您应该将此名称用作命名空间。

我通常将存储库实现和数据访问详细信息放在域命名空间下名为 Persistance 的命名空间中。

应用程序使用自己的名称作为命名空间。

于 2009-02-11T00:04:16.013 回答
0

我会检查 codecampserver 因为那里的设置很常见。

他们有一个核心项目,其中包括应用程序层和域层。即洋葱的内部(http://jeffreypalermo.com/blog/the-onion-architecture-part-1/)。

我实际上喜欢将核心分解成单独的项目来控制依赖的方向。所以通常我有:

MyNamespace.SomethingWeb <-- 多个 UI
MyNamespace.ExtranetWeb <-- 多个 UI

MyNamespace.Application <-- Evans 的应用层,带有 CustomerService
MyNamespace.Domain等类

  • MyNamespace.Domain.Model <-- 实体
  • MyNamespace.Domain.Services <-- 域服务
  • MyNamespace.Domain.Repositories

MyNamespace.Infrastructure <-- repo 实现等。

MyNamespace.Common <-- 所有其他项目都依赖的项目,该项目具有 Logger、Util 类等。

于 2009-02-11T01:00:40.920 回答