CloudNotes领域模型还是相对简单的,并不一定需要采用面向领域驱动的设计方法来解决CloudNotes的领域问题。但出于以下几个方面的原因,我还是采用了面向领域驱动的方式来开发CloudNotes:
接下来,让我们一起对CloudNote的领域模型作些简单的了解。
如果你使用的是Visual Studio 2013/2015旗舰版(Ultimate Edition),那么在打开CloudNotes解决方案后,你可以在CloudNotes.Design项目下,找到CloudNotesModel.classdiagram类图设计文件:
双击该文件,可以打开CloudNotes的领域模型设计视图。到目前为止,CloudNotes的领域模型如下:
咱们暂且不考虑C# class、aggregate root等这些UML构造型,这些内容我会在接下来的文章中详细介绍(顺带会介绍Visual Studio对于模型设计与自动化代码产生的支持)。从该图可以看出,CloudNotes的领域模型还是相对简单的。基本上可以分为三个大部分:笔记、用户以及客户包(ClientPackage)。或许你会考虑,是否可以将这些部分看成是DDD的界定上下文(Bounded Context)呢?
是的,我们可以考虑将CloudNotes的领域模型划分为三个界定上下文:
从DDD角度看,由于模型被划分为多个上下文,而且上下文中的子模型也都是高内聚的(界定的),因此有可能会产生概念或语义上的二义性,而这又是通用语言(Ubiquitous Language)所不能容忍的。比如,一个经典的例子就是银行系统里“Account” 的概念:一个提供在线服务的银行系统,简单地说可以粗略地分为两个界定上下文:银行业务以及在线服务。对于银行业务而言,Account表示客户的银行账户,而对于在线服务而言,Account则又表示客户的在线登录账号,而且一个在线登录账号下可以承载多个银行账户,好比招商银行一网通账号可以有多个银行卡账户和信用卡账户等。那么在做系统设计的时候,遇到Account概念时,如何保证团队交流的准确性呢?因此,需要在领域模型中有一个能够解除这种二义性的“组件”,负责帮助团队人员在整个领域模型的理解与交流上保持一致。这种“组件”就是平时常说的“上下文映射(Context Map)”。有关界定上下文以及上下文映射的详细介绍,可以参考这篇文章:Strategic Domain Driven Design with Context Mapping。
当应用程序所需处理的领域变得很大时,引入界定上下文是很有必要的,从实践角度考虑,使用界定上下文不仅可以在一个相对封闭的范围内,使用一个相对较小的子领域模型,而且还可以从一定程度上提升应用程序的性能:比如某个操作只会发生在系统的某个子领域内部,又如较小的领域模型能够减少系统的处理开销。在Entity Framework 代码先行(Code-First)的开发过程中,可以很好地引入界定上下文的概念,以将复杂的领域模型划分成多个相对较小的简单的领域模型,不仅在模型设计还是在性能上,都有着很好的表现。有关这个话题的更多内容,可以参考我之前翻译的一篇文章:Entity Framework模型在领域驱动设计界定上下文中的应用。
CloudNotes的领域模型相对简单,而且虽然目前后台采用的是Entity Framework,但使用Entity Framework并不是必须的,今后有可能会换成其它的数据持久化系统(比如MongoDB),因此也没有按照上面所述的方式应用界定上下文的相关概念。
由于CloudNotes使用了Apworks框架,因此CloudNotes领域模型中的实体都是使用Guid作为实体键的。这一问题就要引入对Apworks框架的讨论。在Apworks框架中,我们可以看到以下代码:
public interface IEntity { /// <summary> /// Gets or sets the identifier of the entity. /// </summary> Guid ID { get; set; } }
在Apworks中,实体键是Guid类型的。有关实体键的类型选择,在Vaughn Vernon的《实现领域驱动设计》一书中,有相关的描述。概括起来,大致有以下几种情况:
很显然,Apworks采用的就是上述Guid的方式,这样做实现起来比较简单高效,而且Guid值类型的特性,在绝大多数存储系统中都能很好地支持。当然它也有一些弊端,比如可读性差,以及在某些存储系统中性能并不算太好等。无论如何,就Apworks框架本身而言,应该提供一套实体键产生的框架,以便开发人员能够扩展ID值的产生机制,而不应该将ID值类型限定在Guid之上。这在老版本的Apworks中是有类似机制的,只是在考虑到装箱、拆箱带来的性能问题后,就在新的版本中,把这种机制给取消了,也就演变到目前的这种情形。今后我还是会继续改进这部分的设计的。
CloudNotes的领域模型相对简单,实现上采用了Apworks框架,并借用了Visual Studio Ultimate的Architecture功能,对领域模型进行可视化设计和自动化代码生成。或许在今后领域模型会进一步修改,或者逐渐变大,或许也会由此而采用一些新的技术,并产生新的解决方案。到目前为止,CloudNotes的领域模型规模还是很小的,本系列文章也会首先针对当前的这个模型来进行介绍。