前言:
领域是一个组织所做的事情以及其包含的一切,通俗地说,就是组织的业务范围和做事情的方式,也是软件开发的目标范围。比如说淘宝的电商业务,C2C就是电子商务的领域,领域驱动设计就是从领域出发,分析领域内模型以及关系,进而设计软件系统的方法。
比如说电子商务,进行领域设计,通常需要把整个领域拆分成多个子领域,比如说用户、订单、库存、物流、发票等等,强关联的多个子领域内组成一个界限上下文,界限上下文对业务领域范围的描述,对于系统实现而言,可以想象成相当于一个子系统或者是一个模块,界限上下文和子领域共同组织组织的领域,如下:
不同的界限上下文,也就是不同的子系统或者模块之间会有各种的交互合作,如何设计这些交互合同呢,DDD使用上下文映射图来完成,如下:
在DDD中,领域模型对象也被称为实体,每个实体都是唯一的,具有一个唯一标识,一个订单对象是一个实体,一个产品对象也是一个实体,订单ID或者产品ID是他们的唯一标识。实体可能会发生变化,比如说订单的状态会变化,但是他们唯一标识不会变化。
实体设计时DDD的核心所在,首先通过业务分析,识别出实体对象,然后通过相关的业务逻辑设计实体的属性和方法,最重要的是把实体的特征是什么?实体应该承担什么样的职责,不应该承担什么职责,分析的时候要放在业务场景的界限上下文中,而不是想当然的认为实体就应该承担这样的角色。
实际上,并不是领域内的对象都应该被设计为实体,DDD推荐尽可能将对象设计为值对象。比如像住址这样的对象就是一个典型的值对象,也许健在住址上的房子可以被当做一个实体,但是住址仅仅是房子的一个描述,像这样仅仅用来做度量或者描述的对象应该被设计为值对象。
值对象的一个特点是不变性,一个值对象的创建以后就不能改变了,如果地址改变了,那就是一个新的地址,而一个订单实体则可能会经历创建,待支付、已支付、待发货、已发货、待签收、已签收、已评价等等各种变化。
领域实体和界限上下文包含了业务的主要逻辑,但是最终如何构建一个系统,如何将领域实体对外暴露出来,开发一个完整的系统。事实上,DDD支持各种架构方案,比如说典型的分层架构:
领域实体被放置在领域层,通过应用层对领域实体进行包装,最终提供一组访问接口,通过接口层对外开放出来。
六边形架构是DDD中比较知名的一种架构方式,领域模型通过应用程序封装成一个相对比较独立的模块,而不同的外部系统则通过不同的适配器和领域模型交互,比如说可以通过HTTP接口访问领域模型,也可以通过Web Service或者消息队列访问领域模型,只需要为这些不同的访问接口提供不同的适配器即可。
领域驱动设计的技术体系内还有一些方法和概念,但是最核心的还是领域模型本身,通过领域实体以及交互完成业务逻辑处理才是DDD的核心目标。