导航

DDD-澄清领域驱动的基本概念

http://www.codeproject.com/Articles/339725/Domain-Driven-Design-Clear-Your-Concepts-Before-Yo

1.理解领域(Domain):

比如你在参与设计一个建筑物,需求是:

. 规定的土地大小

. 一共6层

. 每层4个屋子

那么,这个例子的Domain是什么?

领域是建筑物?也许,但是注意如果我们把建筑物作为domain,我们可能失去一些需求细节。我们要建造一个给人住的建筑物还是别的呢?所以需要缩小我们的领域到"居住的建筑物“。现在,当我们跟我们的工程师讨论我们的工作时将会更加具体而有意义。承包商要你见一个6层,每层4个屋子的建筑物。然后你派一个工程师告诉他让他开始建造,他也许会无从下手,但是你告诉他是建一个给人居住的,我想他们做一些有效的分析设计了。

2. 同一语言(Ubiquitous language):

开发人员需要和用户或者领域专家使用大家都可以明白的语言进行交流。更重要的是使用业务术语,而不是技术术语。

下面列举一些例子,

例子1,

 错误的语言:

小卧室的长和宽的比例应该是4:3

正确的语言:

小孩的卧室应该20ft长, 15ft 宽。

注意"小卧室” "比例“ 都是专业术语。如果用"小孩的房间” “客厅” 更加容易懂。比较人性化。

 

3. 上下文和界定的上下文(Contexts and Bounded Contexts):

一个Bounded Context 可以被看作是一个微型的应用程序,包括自己的Domain,代码和持久化机制, 每个Bounded Context需要内部逻辑一致,之间独立。

让我们以电子商务为例子:最开始你明白它是个购物的东西(shopping context.),再往细里看,我们能发现其他的东西(Context), 像库存、快递、财务等。

将一个大的应用分解成不懂的boudned contexts可以让我们的程序更加模块化。

既然我们已经知道了界定的上下文,那么我们接着写“可居住的建筑的" Domain:

. 供电

. 停车场

. 屋子(apartment)

. 等等

接着我们来讨论屋子(apartment), 每个屋子都是由居室组成的(一居室、二居室、三居室),每个居室都有不同的东西(elements),像窗户、门等。现在问两个关于窗户的问题:

 问题1: 你能想象没有居室的窗户吗?(意思是说窗户离开了居室就没有存在的意思了。)

 问题2: Does a window have any identity without the room it is residing in?(好像也是窗户没有可以寄宿的居室没有意义)

 界定上下文的资料:

http://msdn.microsoft.com/en-us/magazine/jj883952.aspx

http://www.cnblogs.com/daxnet/archive/2013/03/22/2976282.html

http://shop.oreilly.com/product/0636920022237.do

 

 

4. 实体(Entity):”这是我的实体,这里有很多差不多的东西,但是这个是我的“

唯一标识是实体最主要的特征。在整个系统里是唯一的。如下这个东西都算是实体:

. 你屋子的卧室

. 在codeproject的文章

 

5. 值对象(Value Object):

与实体相反,它最大的特征是没有唯一标识。只读(immutable),一旦被创建,就不能被改变,但是你可以创建一个新的。值对象的意图是用它的属性来代表事物。

比如:

. 房间里的窗户

. 你QQ里某个朋友的地址

. 你在网站搜索的条件

! 注意, 一个值对象在某些情况下可能变成一个实体对象。比如你的搜索功能有需求希望把搜索条件存到数据库里,用户可以在其它时候使用这些搜索条件。这时它们就有了唯一标识。

在DDD中,entities 和 value objects都可以独立的存在。但是在有些情况下, entity or VO可能没有值如果没有context时:

比如:

. 窗户只能被放到居室里

. 订单说明存在的前提是有这么一个订单

. 问题详情存在的前提是有一个问题

 

public class Money {
  public readonly Currency Currency;
  public readonly decimal Amount;

  public Money(decimal amount, Currency currency) {
    Amount = amount;
    Currency = currency;
  }

  public Money AddFunds(Money fundsToAdd) {
    // because the money we're adding might
    // be in a different currency, we'll service 
    // locate a money exchange Domain Service.
    var exchange = ServiceLocator.Find<IMoneyExchange>();
    var normalizedMoney = exchange.CurrentValueFor(fundsToAdd,         this.Currency);
    var newAmount = this.Amount + normalizedMoney.Amount;
    return new Money(newAmount, this.Currency);
  }
}

public enum Currency {
  USD,
  GBP,
  EUR,
  JPY
}

 

6. 聚合和聚合根(Aggregate and Aggregate Root):

上面的例子告诉我们:

. 居室、订单、问题是无的Aggregate root.

. 另一面,窗户、订单详情、问题详情是我们的Aggregate

”一组(cluster)相关的对象被看作一个整体 regards to data changes."

所有的组(cluster)的对象被视为aggregate.

所有外部对象要访问这个组(cluster)必须通过一个 实体根(single root Entity). 这个实体根就是 aggregate root.

比如:

. 问题详情不需要被保存,除非相应的问题需要被保存

. 问题详情不需要被检索,除非相应的问题被检索

7. Persistence Ingorance:

在DDD里,我们的目标是建立领域模型。我们需要找到相关的对象(objects)来完成我们程序的功能。我们需要找到对象之间的关系以及它们之间是怎么交互的。我们需要发现我们的领域模型是否满足客户的业务需求。 数据库在这里有什么用?我们不需要知道怎样和到哪里持久化我们的领域对象,甚至当我在进行领域建模的时候都不用考虑数据需要持久化。

不考虑持久化可以让我们的领域模型和持久层解耦。最终将实现持久层和领域西模型的分离关注。但是,是的,真正的程序确实离不开数据库,但是领域模型不要知道它。我们将使用"Repository"来管理持久层。(就是持久层的对外接口?)

8. Repository: "Repository commonly refers to a location for storage, often for safety or preservation"

在系统中,Repository负责存储、访问数据。让Domain Model来弄(concern to how and where) 持久数据是不合理的。比如Sql server, oracle, xml, text file...

Repository 协调(mediates) 领域和数据映射,通过collection-like的结构来访问领域对象。它更像是一个数据存储的装饰(facade),看起来像一个领域的集合( collection).

Repository is Not A data Access Layer.

注意Repository 是用聚合根的方式而不是数据的方式存在的。我们可以添加一个聚合根到它的集合(collection),也可以获得一个想要的聚合根。这个与我们传统的DAL返回一个数据集合很不一样。

实现Reposity需要注意的东西:

. 首先你得有一个通用的接口 IRepository.

. 然后你需要抽象的实现这个接口 abstract implementation.

. 你会有一个INhRepository 来代表你的持久化机制(i.e. Nhibernate), 它继承自IRepository,

. 你将通过NhRepository实现INhRepository

. NHGenericRepository继承自NhRepository并且实现IGenericNhRepository.

. 为聚合根选择合适的Repository.

9. Domain Service:

如果实体和值对象是领域中的"things",那么领域服务就是领域的"Actions, Operations and Activities".

难道不能直接把逻辑放到实体中吗? 当然可以,但是最好是放于实体自己或它的孩子相关的逻辑。我们可以把领域服务看成是业务逻辑和领域操作的装饰。(facade)

 

Great DDD Resources 

http://www.dddcommunity.org/  

http://thinkddd.com/ 

http://www.infoq.com/minibooks/domain-driven-design-quickly 

http://thinkddd.com/assets/2/Domain_Driven_Design_-_Step_by_Step.pdf 

http://www.dddcommunity.org/library/young_2010 

http://www.dddcommunity.org/library/evans_2010 

http://blog.fossmo.net/post/Command-and-Query-Responsibility-Segregation-(CQRS).aspx 

http://msdn.microsoft.com/en-us/library/ff649690.aspx 

 

posted on 2014-12-27 23:28  水中游  阅读(247)  评论(0)    收藏  举报