《领域驱动设计》基础知识汇总
- 格式:docx
- 大小:473.92 KB
- 文档页数:7
《领域驱动设计》基础知识汇总(转)1. 什么是领域(Domain)我们所做的软件系统的目的都是来解决一系列问题,例如做一个电商系统来在线销售自己企业的产品;做一个灰度发布平台来提升服务的质量和稳定性。
任何一个系统都会属于某个特定的领域,例如:•论坛是一个领域:要做一个论坛,那这个论坛的核心业务是确定的:比如用户发帖、回帖等核心基本功能;•电商系统是一个领域:只要是电商领域的系统,那核心业务就是:商品浏览、购物车、下单、减库存、付款交易等核心环节;同一个领域的系统都具有相同的核心业务,因为他们要解决的问题的本质是类似的。
因此可以推断:一个领域本质上可以理解为一个问题域。
只要确定了系统所属的领域,那么这个系统的核心业务,即要解决的关键问题就基本确定了。
通常我们说,要成为一个领域的专家,必须要在这个领域深入研究很多年才行,只有这样才会遇到非常多的该领域的问题,积累了丰富的经验。
2.界限上下文(Bounded Context)通常来说,一个领域有且只有一个核心问题,我们称之为该领域的『核心子域』。
在核心子域、通用子域、支撑子域梳理的同时,会定义出子域中的『限界上下文』及其关系,用它来阐述子域之间的关系。
界限上下文可以简单理解成一个子系统或组件模块。
例如:下图是对酒店管理的子域和界限上下文的梳理:3. 领域模型(Domain Model)领域驱动设计(Domain-Driven Design)分为两个阶段:1.以一种领域专家、设计人员、开发人员都能理解的通用语言作为相互交流的工具,在交流的过程中发现领域概念,然后将这些概念设计成一个领域模型;2.由领域模型驱动软件设计,用代码来实现该领域模型;由此可见,领域驱动设计的核心是建立正确的领域模型。
领域模型具有以下特点:1.对具有某个边界的领域的一个抽象,反映了领域内用户业务需求的本质。
它属于『解决问题空间』。
领域模型是有边界的,只反应了我们在领域内所关注的部分,包括实体概念(如:货物,书本,应聘记录,地址等),以及过程概念(如:资金转账等);2.提高软件的可维护性,业务可理解性以及可重用性。
领域驱动架构设计详细讲解(⼀)⼀、什么是DDD?DDD⼜叫领域驱动设计,它是⼀种软件开发的思想,不是具体的技术或者框架,它的核⼼是维护⼀个能够反映领域概念的模型,通过⼀些模式和约束来指导团队进⾏统⼀的设计开发。
⼆、为什么要使⽤DDD?从技术层⾯进⾏分层,每层都在关注⾃⼰的事情,⽐如领域层关注业务逻辑,仓储层关注持久化数据,应⽤服务层关注协调领域层和仓储层实现某⼀个业务,接⼝层关注暴露应⽤服务接⼝给外界调⽤从业务维度,将⼤的系统划分为多个领域界限,可以选择将不同的界限分配给不同的团队、不同的界限使⽤不同的仓储,实现界限内是⾼内聚⽽界限之间是低耦合的由于DDD只是⼀种开发理念,所以要想在项⽬中发挥他的作⽤,我们需要先搞懂它⾥⾯的⼀些基本概念和核⼼组件,然后基于它搭建⼀个轻量级的框架。
三、DDD的核⼼组件1.领域界限:对于⼀个系统⽽⾔,我们对其按照不同的领域划分不同的界限,不同的领域界限之间可以是相互独⽴的。
每个领域内都有⾃⼰独⽴的领域逻辑、数据持久化和接⼝等。
2.聚合的概念:通常我们会将多个实体和值对象进⾏组合来表达⼀个完整的概念,⽐如订单实体、订单详情实体、订单收货信息组成了⼀个完整的订单概念,他们的⽣命周期是⼀样的,在进⾏持久化时也应该进⾏统⼀持久化。
3.聚合根的概念:对于⼀个聚合⽽⾔,必须有⼀个对象能够表达这个聚合的总概念,外界想要对这个聚合进⾏持久化的操作时,必须通过这个总概念进⾏协调,通过它来保证业务⼀致性,那么这个对象我们就称之为聚合根。
在⼀个聚合中有且只有⼀个聚合根,想要访问聚合内的对象,必须要通过聚合根才能进⾏访问(当然,其他的实体可以在外界需要查询时临时调⽤),聚合根拥有唯⼀的标识,也拥有业务⽣命周期,其本质也是实体。
⽐如订单聚合中的订单实体即为这个聚合的聚合根。
4.实体的概念:实体是⼀个有业务⽣命周期的概念,拥有唯⼀标识⽤于标识和区分。
⽐如⼀个订单对象就是⼀个实体。
5.值对象的概念:值对象是⼀个⽆业务⽣命周期的概念,通常⽤于定义聚合中的某⼀个复杂的对象属性,不需要定义标识进⾏区分。
《领域驱动设计》基础知识汇总《领域驱动设计》(Domain-Driven Design,简称DDD)是一种软件开发方法论,它将软件开发过程中的关注点从技术细节转移到业务领域上。
DDD强调将业务需求和软件模型紧密对应,以便更好地理解业务需求,并将其准确地转化为可执行的软件模型。
以下是《领域驱动设计》的基础知识汇总。
1.领域驱动设计的核心思想是通过将知识转化为模型来解决复杂问题。
领域模型是对业务领域知识的抽象和表达,它将业务对象、业务规则和业务流程等概念化地表示出来。
2.领域驱动设计强调领域专家参与,并与开发团队紧密合作。
领域专家是对业务领域非常熟悉的人,他们能够提供与业务相关的知识和经验,并对软件开发过程中的需求和模型进行指导。
3.领域驱动设计提倡使用统一的语言来描述业务领域。
该语言应该由领域专家和开发团队共同创造,以最大程度地减少沟通障碍并提高开发效率。
4.领域驱动设计中的聚合是一个非常重要的概念。
聚合是一个具有内聚性的对象集合,它们被视为一个整体并按照一定的规则进行操作和管理。
聚合根是聚合中最核心的对象,它负责管理整个聚合的状态和行为。
5.领域驱动设计中的领域事件是一种重要的机制,用于解耦和通信。
领域事件是业务领域中发生的一些关键事件,它们被抽象为领域事件,并且可以被其他对象订阅和处理。
6.领域驱动设计中的领域服务是一种封装了业务逻辑的对象,它不属于任何聚合和实体,负责处理那些跨聚合的复杂业务逻辑。
领域服务可以与其他对象进行协作,但它不应该持有状态。
7.领域驱动设计中的领域模型需要经过持久化以便在不同的系统之间共享和使用。
领域模型可以通过使用ORM框架或其他数据持久化技术来实现,并根据需要进行优化。
8.领域驱动设计强调使用领域驱动设计模式来解决常见的设计问题。
这些模式包括实体、值对象、仓储、工厂、规范等,它们提供了一些通用的解决方案,可以帮助开发人员更好地组织和管理领域模型。
9.领域驱动设计需要采用迭代增量的方式进行开发,将复杂的需求拆分成小的任务,并通过测试驱动开发的方式逐步实现。
ddd领域驱动设计pdf
领域驱动设计(DDD)是一种软件开发方法,它强调通过深入理解业务领域来指导系统设计和建模。
DDD的目标是创建一个在技术和业务之间建立有效沟通的共享模型。
以下是DDD中的一些关键概念:
1.领域(Domain):DDD关注的是业务领域,即软件系统所要解决的问题的核心领域。
领域包含了业务规则、流程和概念。
2.实体(Entity):在DDD中,实体是领域中具有唯一标识的对象,其状态和行为由其标识决定。
实体通常对应领域中的具体事物。
3.值对象(Value Object):值对象是没有唯一标识的对象,它们的相等性由其属性决定。
值对象通常用于描述领域中的属性集。
4.聚合根(Aggregate Root):聚合根是实体和值对象的集合,其中一个对象被定义为聚合的根。
聚合根负责维护聚合内部对象的一致性。
5.仓储(Repository):仓储是用于存储和检索领域对象的机制,它隐藏了数据存储的细节,让应用程序可以通过领域模型而不是数据库表进行操作。
6.领域服务(Domain Service):领域服务是一种包含业务逻辑的服务,它不属于任何特定的实体或值对象,而是处理领域中的横切关注点。
7.限界上下文(Bounded Context):限界上下文定义了领域模型的边界,确保在不同上下文中的术语和概念不会产生混淆。
DDD强调建立一个共享的、深刻理解的领域模型,通过领域专家和开发团队之间的协作来不断迭代和改进这个模型。
这有助
于更好地反映业务需求,提高软件系统的可维护性和灵活性。
领域驱动设计详解领域驱动设计(Domain-Driven Design,DDD)是一种软件开发方法论,旨在解决复杂领域中的问题。
它强调软件开发应该以领域为核心,将领域专家的知识融入到设计中,以便更好地理解和解决领域中的问题。
在领域驱动设计中,领域是指问题领域的具体范围,例如电子商务、银行业务等。
领域专家是在该领域中具备丰富知识和经验的人员。
通过与领域专家的密切合作,开发团队可以更好地理解和解决问题。
领域驱动设计的核心概念包括领域模型、限界上下文和聚合根。
领域模型是对领域的抽象和描述,它包含了领域中的实体、值对象、服务和领域事件等。
领域模型应该是由领域专家和开发团队共同定义和演化的,以确保模型能够准确地反映领域的实际情况。
限界上下文是指领域模型的边界,它定义了在不同上下文中的含义和范围。
一个限界上下文可以是一个子系统、一个模块或一个服务,它负责管理自己的领域模型和业务逻辑。
通过明确限界上下文,可以确保不同上下文之间的交互和协作更加清晰和有效。
聚合根是领域模型中的重要概念,它是一组相关对象的根节点。
聚合根负责维护聚合内部的一致性和完整性,并且提供了访问和操作聚合内部对象的接口。
通过聚合根,可以将复杂的领域模型分解为更小的组件,提高系统的可维护性和灵活性。
在实施领域驱动设计时,需要遵循一些基本原则和模式。
要尽量保持领域模型的简洁和清晰。
领域模型应该只包含与领域相关的概念和逻辑,避免引入与领域无关的技术细节。
同时,要注重模型的可复用性和可扩展性,以便应对未来的需求变化。
要进行持续的领域建模和迭代开发。
领域模型应该是一个持续演化的过程,通过与领域专家的交流和反馈,不断优化和完善模型。
同时,要采用敏捷开发的方法,以快速响应需求变化,并及时调整和修改领域模型。
要注重领域模型和代码的质量。
领域模型应该是可测试和可验证的,以确保模型的正确性和一致性。
同时,要采用合适的设计模式和技术,以提高代码的可读性、可维护性和可扩展性。
《领域驱动设计》⼲货整理Repository设计思路像模块化系统、模块化代码⼀样,模块化数据库中的表。
使得每个模块之间有清晰的界限。
Repository代码设计1. 可以将Repository理解为⼀个集合(这⾥的集合更偏重于是Collection,⽽不是Set),它包括了对存储对象基本的增删改查(CURD)功能。
同时,Repository还包括满⾜领域层的⼀些特定的功能(注:在Repository中包括这些功能是合理的,⾸先这些功能是底层设施应该提供给上层的领域层的,其次在这⾥实现可以更好的利⽤底层设施的特点来进⾏性能优化)(注:在⼀般领域驱动设计的项⽬中分层都是上层依赖下层,这⾥的设计却更偏向于下层基础设施层依赖于上层领域层。
应该可以发现,这⾥Respository的需要包含的功能都是由上层领域层需要什么决定的,⽽不是由下层基础设计层能提供什么决定的。
笔记认为这样的设计其实是更合理的,《Clean Architecture》⼀书的作者也与笔者持有相同的观点。
这个问题的讲述可以单独写⼀篇博客,再这篇⽂章⾥不再细究)。
2. 不是每张表都需要有⼀个Repository(在Mybatis中aka:Mapper)与之对应,更准确的说:应该将数据库中的全部表表聚积到⼏个根对象上(聚积⽅法后⾯讲),这个根对象应该有Repository,⽽聚积在这个根上的对象不应该有Repository。
对这些⾮根对象的访问,应该通过于根对象的对象关系来实现。
3. (注:和第⼀条紧密相关,我暂时没有想清楚他俩之间的联系)正确的组合搜索于关联。
搜索,即通过给Repository传递查询参数来获取对象;关联,即通过要访问对象与通过搜索得到的对象的关联来获取对象。
4. Repository应该是⼀个接⼝,将其实现与领域层的需求解耦。
同时,⽅便测试时进⾏插桩和mock。
5. 虽然通过接⼝解耦了Repository与领域层,但是即便是领域层的开发⼈员,也应该清楚Repository的实现。
领域驱动设计详解领域驱动设计(Domain-Driven Design,简称DDD)是一种软件开发方法,旨在帮助解决复杂领域的设计和开发问题。
它强调以领域为核心,通过深入理解领域知识和业务规则,将软件设计与领域模型紧密结合,从而提高软件系统的质量和可维护性。
1. 为什么需要领域驱动设计?在传统的软件开发中,往往将重点放在技术层面,而忽略了对领域知识的深入理解。
这导致了软件系统与实际业务需求之间的脱节,使得软件难以满足用户的真正需求。
而领域驱动设计的出现正是为了解决这个问题。
它通过将业务专家、开发人员和设计人员紧密合作,共同创建一个清晰的领域模型,以满足业务需求并提高软件质量。
2. 领域模型的核心概念在领域驱动设计中,领域模型是核心概念之一。
领域模型是对业务领域的抽象和描述,它包含了实体、值对象、聚合根、领域服务等元素。
实体是具有唯一标识的对象,值对象是没有唯一标识的对象,聚合根是一组相关对象的根,领域服务是领域模型中的动作和操作。
通过定义和使用这些元素,可以更好地表达业务需求,并将其映射到软件系统中。
3. 领域驱动设计的核心原则领域驱动设计有一些核心原则,包括战略设计和战术设计。
战略设计关注的是领域模型的整体结构和组织,它主要包括限界上下文、通用语言等概念。
限界上下文是指将整个领域划分为不同的上下文边界,每个上下文都有自己的领域模型和业务规则。
通用语言是指在领域专家和开发人员之间建立共同的语言,以便更好地沟通和理解业务需求。
4. 领域驱动设计的实施过程领域驱动设计的实施过程通常包括以下几个步骤:- 深入理解业务需求:与领域专家进行密切合作,了解业务规则和需求,形成共同的理解。
- 创建领域模型:根据业务需求,定义领域模型的各个元素,包括实体、值对象、聚合根、领域服务等。
- 持续迭代和优化:根据实际情况,不断迭代和优化领域模型,以适应业务的变化和发展。
- 划分限界上下文:将整个领域划分为不同的上下文边界,每个上下文都有自己的领域模型和业务规则。
软件架构的模式与思想:领域驱动设计软件架构是指在软件开发过程中,将系统分解成多个相互关联的部分,并确定它们的交互关系和组织方式的过程。
一个合理的软件架构能够提高软件的灵活性、可维护性和可扩展性。
在众多的软件架构模式中,领域驱动设计(Domain-Driven Design,DDD)是一种被广泛应用的架构思想,它将软件的设计与领域模型的概念相结合,从而实现更好的软件设计和开发。
下面将详细介绍软件架构模式与思想——领域驱动设计的相关内容:1. 领域驱动设计的基本思想- 领域的概念:将软件设计与实际业务领域相结合,即将软件系统划分为多个领域,并在每个领域中定义相应的业务规则和模型。
- 领域模型:以面向对象的方式表达领域概念,通过实体、值对象和聚合根等元素构建领域模型,同时通过领域事件和领域服务来实现领域模型之间的交互。
- 领域驱动设计思想的优势:能够提高软件系统的可扩展性、可维护性和可理解性,同时也能使开发团队更好地理解业务需求和系统功能。
2. 领域驱动设计的步骤- 领域建模:通过与领域专家的密切合作,了解业务领域的各个方面,识别出领域模型中的对象、属性和关系,并进行相应的建模工作。
- 设计聚合:将领域模型中的一组相关对象进行组织和管理,形成一个聚合根,并定义聚合根的边界和操作。
- 实现领域逻辑:在聚合根中实现领域的业务逻辑,包括验证规则、状态转换等。
同时,通过领域服务和领域事件来处理领域模型之间的交互。
- 构建应用层:在应用层中,通过调用领域模型中的方法来实现具体的业务流程。
同时,也可以在应用层中进行数据转换和验证等工作。
- 构建用户界面:在用户界面中,通过调用应用层的接口来展示领域模型的信息,并与用户进行交互。
3. 领域驱动设计的模式- 聚合模式:将领域模型中的对象进行组织和管理,形成一个聚合根。
聚合根内的对象是不可直接访问的,只能通过聚合根的方法来进行操作。
这样可以保证领域模型的一致性和完整性。
领域驱动设计(DDD)中简单易用的10种技巧领域驱动设计(Domain-Driven Design,DDD)是一种软件开发方法,旨在帮助开发人员更好地理解和解决复杂业务领域中的问题。
DDD提供了一系列的技巧和原则,以帮助开发人员设计出清晰、可维护和可扩展的软件系统。
下面是10种简单易用的DDD技巧:1. 对象映射(Object Mapping):在DDD中,领域模型对象和数据访问对象之间需要进行映射。
可以使用ORM(对象关系映射)工具来实现对象映射,同时需要注意领域模型对象的不可变性。
2. 领域事件(Domain Event):领域事件是一种用于描述系统中发生的重要事情的机制。
通过引入领域事件,可以更好地跟踪领域模型对象之间的关系和交互。
3. 聚合根(Aggregate Root):聚合根是一种具有整体性和一致性的领域模型对象。
通过将一组相关的领域模型对象聚合到一个聚合根中,可以简化系统的设计和实现,同时提高性能。
4. 领域服务(Domain Service):领域服务是一种处理领域模型对象之间的复杂业务逻辑的机制。
通过引入领域服务,可以将复杂的业务逻辑封装到独立的服务中,提高系统的灵活性和可测试性。
5. 值对象(Value Object):值对象是一种没有唯一标识符的对象,其属性值一旦确定就不可更改。
值对象通常用于描述领域模型中的属性集合,比如邮政地址、日期范围等。
6. 聚合(Aggregate):聚合是一种逻辑上紧密相关的领域模型对象的集合,其中一个对象被指定为聚合根。
通过引入聚合的概念,可以简化系统的设计和管理领域模型对象之间的关系。
7. 领域驱动设计模式(DDD Patterns):DDD提供了一系列的设计模式,用于解决在领域驱动设计中常见的问题。
一些常见的模式包括实体(Entity)、工厂(Factory)、仓储(Repository)等。
8. 领域模型的一致性(Consistency of the Domain Model):在领域驱动设计中,一致性是非常重要的。
《领域驱动设计》基础知识汇总(转)1. 什么是领域(Domain)我们所做的软件系统的目的都是来解决一系列问题,例如做一个电商系统来在线销售自己企业的产品;做一个灰度发布平台来提升服务的质量和稳定性。
任何一个系统都会属于某个特定的领域,例如:•论坛是一个领域:要做一个论坛,那这个论坛的核心业务是确定的:比如用户发帖、回帖等核心基本功能;•电商系统是一个领域:只要是电商领域的系统,那核心业务就是:商品浏览、购物车、下单、减库存、付款交易等核心环节;同一个领域的系统都具有相同的核心业务,因为他们要解决的问题的本质是类似的。
因此可以推断:一个领域本质上可以理解为一个问题域。
只要确定了系统所属的领域,那么这个系统的核心业务,即要解决的关键问题就基本确定了。
通常我们说,要成为一个领域的专家,必须要在这个领域深入研究很多年才行,只有这样才会遇到非常多的该领域的问题,积累了丰富的经验。
2.界限上下文(Bounded Context)通常来说,一个领域有且只有一个核心问题,我们称之为该领域的『核心子域』。
在核心子域、通用子域、支撑子域梳理的同时,会定义出子域中的『限界上下文』及其关系,用它来阐述子域之间的关系。
界限上下文可以简单理解成一个子系统或组件模块。
例如:下图是对酒店管理的子域和界限上下文的梳理:3. 领域模型(Domain Model)领域驱动设计(Domain-Driven Design)分为两个阶段:1.以一种领域专家、设计人员、开发人员都能理解的通用语言作为相互交流的工具,在交流的过程中发现领域概念,然后将这些概念设计成一个领域模型;2.由领域模型驱动软件设计,用代码来实现该领域模型;由此可见,领域驱动设计的核心是建立正确的领域模型。
领域模型具有以下特点:1.对具有某个边界的领域的一个抽象,反映了领域内用户业务需求的本质。
它属于『解决问题空间』。
领域模型是有边界的,只反应了我们在领域内所关注的部分,包括实体概念(如:货物,书本,应聘记录,地址等),以及过程概念(如:资金转账等);2.提高软件的可维护性,业务可理解性以及可重用性。
领域模型确保了我们的软件的业务逻辑都在一个模型中,帮助开发人员相对平滑地将领域知识转化为软件构造;3.贯穿软件分析、设计、开发的整个过程。
领域专家、设计人员、开发人员面向同一个模型进行交流,彼此共享知识与信息,所以可以防止需求走样,让软件开发人员做出来的软件真正满足需求;要建立正确的领域模型并不简单,需要领域专家、设计、开发人员积极沟通共同努力,然后才能使大家对领域的认识不断深入,从而不断细化和完善领域模型;4.为了让领域模型看的见,使用的常用表达领域模型的方式:图、代码或文字;5.重要性:领域模型是整个软件的核心,是软件中最有价值和最具竞争力的部分;设计足够精良且符合业务需求的领域模型能够更快速的响应需求变化;4. 领域通用语言由软件专家和领域专家合作开发一个领域的模型是有必要的。
开发过程中,开发人员以类、算法、设计模式、架构等进行思考与交流。
但领域专家对此一无所知,他们对技术上的术语没有太多概念,只了解特有的领域专业技能,例如:在空中交通监控样例中,领域专家知道飞机、路线、海拔、经度、纬度,他们有自己的术语来讨论这些事情。
软件专家和领域专家交流过程中,需要做翻译才能让对方理解这些概念。
领域驱动设计的一个核心原则是使用一种基于模型的语言。
使用模型作为语言的核心骨架,要求团队在进行所有的交流是都使用一致的语言,在代码中也是这样,这种语言被称为『通用语言』5.建模思考的问题:用户需求『用户需求』不能等同于『用户』,捕捉『用户心中的模型』也不能等同于『以用户为核心设计领域模型』。
设计领域模型时不能以用户为出发点去思考问题,不能老想着用户会对系统做什么;而应该从一个客观的角度,根据用户需求挖掘出领域内的相关事物,思考这些事物的本质关联及其变化规律作为出发点去思考问题。
领域模型是排除了人之外的客观世界模型,包含了人所扮演的参与者角色。
但是一般情况下不要让参与者角色在领域模型中占据主要位置,否则各个系统的领域模型将变得没有差别,因为软件系统就是一个人机交互的系统,都是以人为主的活动记录或跟踪。
例如:•论坛中如果以人为主导,那么领域模型就是:人发帖,人回帖,人结贴,等等;•货物托运系统中如果以人为主导,就变成了:托运人托运货物,收货人收货物,付款人付款,等等;以一个货物运输系统为例子简单说明一下。
在用户需求相对明朗之后,这样描述领域模型:•一个Cargo(货物)涉及多个Customer(客户,如托运人、收货人、付款人),每个Customer承担不同的角色;•Cargo的运送目标已指定,即Cargo有一个运送目标;•由一系列满足Specification(规格)的Carrier Movement(运输动作)来完成运输目标;以上描述没有从用户的角度去描述领域模型,而是以领域内的相关事物为出发点,考虑这些事物的本质关联及其变化规律的:•以货物为中心,把客户看成是货物在某个场景中可能会涉及到的关联角色,如货物会涉及到托运人、收货人、付款人;•货物有一个确定的目标,货物会经过一系列的运输动作到达目的地。
以用户为中心来思考领域模型的思维只是停留在需求的表面,而没有挖掘出真正的需求的本质。
领域建模时需要努力挖掘用户需求的本质,这样才能真正实现用户需求。
6. 经典分层架构用户界面/展示层:1)请求应用层获取用户所需的展示数据;2)发送命令给应用层执行用户的命令应用层:薄薄的一层,定义软件要完成的任务。
对外为展示层提供各种应用功能,对内调用领域层(领域对象或领域服务)完成各种业务逻辑。
应用层不包含业务逻辑领域层:表达业务概念、业务状态信息及业务规则,是业务软件的核心基础设施层:为其他层提供通用的技术能力,提供了层间通信;为领域层提供持久化机制。
7. 使用的模式7.1. 总览图7.2. 关联的设计关联在领域建模的过程中非常重要,关联的设计可以遵循如下的一些原则:•关联尽量少。
对象之间复杂的关联容易形成对象的关系网,对于理解和维护单个对象很不利,同时也很难划分对象与对象之间的边界;另外,减少关联有助于简化对象之间的遍历;•关联尽量保持单向的关联;•在建立关联时,需要挖掘是否存在关联的限制条件。
如果存在,那么最好把限制条件加到关联上,往往这样的限制条件能将关联化繁为简,即将多对多简化为1对多,或将1对多简化为1对1;7.3. 实体(Entity)实体就是领域中需要唯一标识的领域概念。
因为我们有时需要区分是哪个实体:有两个实体,如果唯一标识不一样,那么即便实体的其他所有属性都一样,也认为他们是两个不同的实体。
不应该给实体定义太多的属性或行为,而应该寻找关联,将属性或行为转移到其他关联的实体或值对象上。
比如:Customer 实体,有一些地址信息,由于地址信息是一个完整的有业务含义的概念,所以我们可以定义一个 Address 对象,然后把 Customer 的地址相关的信息转移到 Address 对象上。
如果没有 Address 对象,而把这些地址信息直接放在 Customer对象上,然后对于一些其他的类似Address的信息也都直接放在Customer 上,会导致Customer 对象很混乱,结构不清晰,最终导致它难以维护和理解。
7.4. 值对象(Value Object)并不是每一个事物都必须有一个唯一标识。
就以上面的地址对象 Address 为例,如果两个Customer 的地址信息是一样的,我们就会认为这两个 Customer 的地址是同一个。
用程序的方式来表达就是:如果两个对象所有属性的值都相同,我们会认为它们是同一个对象,那么就可以把这种对象设计为值对象。
值对象的特征:•值对象没有唯一标识,这是它和实体的最大不同。
值对象在判断是否是同一个对象时是通过它们的所有属性是否相同,如果相同则认为是同一个值对象。
在区分是否是同一个实体时,只看实体的唯一标识是否相同,而不管实体的属性是否相同。
•值对象是不可变的,即所有属性都是只读的,所以可以被安全的共享。
应该给值对象设计的尽量简单,不要让它引用很多其他的对象。
值对象只是一个值,类似(int a = 3)中的『3』,只不过是用对象来表示。
值对象虽然是只读的,是一个完整的不可分割的整体,但是可以被整个替换掉:类似(a = 4)把a的值由『3』替换为为『4』,当修改 Customer 的 Address 对象引用时,不是通过 Customer.Address.Street 这样的方式来修改属性,可以这样做:Customer.Address = new Address(…)7.5. 领域服务(Domain Service)领域中的一些概念不太适合建模为对象(实体对象或值对象),因为它们本质上就是一些操作、动作,而不是事物。
这些操作往往需要协调多个领域对象。
如果强行将这些操作职责分配给任何一个对象,则被分配的对象就是承担一些不该承担的职责,从而会导致对象的职责不明确很混乱。
DDD认为领域服务模式是一个很自然的范式用来对应这种跨多个对象的操作。
一般的领域对象都是有状态和行为的,而领域服务没有状态只有行为。
领域服务还有一个很重要的功能就是可以避免领域逻辑泄露到应用层。
因为如果没有领域服务,那么应用层会直接调用领域对象完成本该是属于领域服务该做的操作,需要了解每个领域对象的业务功能,以及它可能会与哪些其他领域对象交互等一系列领域知识。
这样一来,领域层可能会把一部分领域知识泄露到应用层。
对于应用层来说,通过调用领域服务提供的简单易懂且意义明确的接口肯定也要比直接操纵领域对象容易的多。
说到领域服务,还需要提一下软件中一般有三种服务:应用层服务、领域服务、基础服务。
从以下的例子中可以清晰的看出每种服务的职责:应用层服务1.获取输入(如一个XML请求)2.发送消息给领域层服务,要求其实现转帐的业务逻辑3.领域层服务处理成功,则调用基础层服务发送Email通知领域层服务1.获取源帐号和目标帐号,分别通知源帐号和目标帐号进行扣除金额和增加金额的操作2.提供返回结果给应用层基础层服务1.按照应用层的请求,发送Email通知7.6. 聚合及聚合根(Aggregate,Aggregate Root)聚合定义了一组具有内聚关系的相关对象的集合,以及对象之间清晰的所属关系和边界,避免了错综复杂的难以维护的对象关系网的形成。
我们把聚合看作是一个修改数据的单元。
聚合有以下特点:1.每个聚合有一个根和一个边界:根是聚合内的某个实体;边界定义了一个聚合内部有哪些实体或值对象;2.聚合根是外部可以保持对聚合引用的唯一元素,负责与外部其他对象打交道并维护自己内部的业务规则。