微服务详解(四):领域驱动设计

微服务详解(一):概述

微服务详解(二):解决方案

微服务详解(三):设置开发环境

微服务详解(四):领域驱动设计

微服务详解(五):实现微服务

微服务详解(六):部署与测试

微服务详解(七):微服务的安全性

微服务详解(八):最佳做法和一般原则

微服务详解(九):故障排除指南

领域驱动设计(domain driven design ,DDD)

1.领域驱动设计的基本原理

企业或者云应用程序是用来解决业务问题和其他现实世界的问题的。若没有所在领域的知识,就不能解决这些问题。

拥有领域知识是解决问题的一个必备条件;

模型是该领域的一种抽象或者蓝图;

从逻辑上对它们进行分组并创建模块,每个模块可以单独处理,也可以使用类似的方法进行划分。我们可以遵循这一过程,知道达到单元级别或者我们不能将它进一步划分为止。一个复杂的项目可能会有多次这样的迭代,而同样一个简单地项目可能只有单个迭代;

一旦定义好了模型,并将其良好的记录在文档中,就可以转到下一个阶段——代码设计;

领域模型提供了高层次的解决方案(软件/应用程序)的架构,而代码实现作为一种能工作的模型给了领域模型生命;

2.组成部分

1.普遍存在的语言

设计模型是软件设计师、领域专家和开发人员集体的工作。

因此,它们需要使用共同的语言来交流。

统一建模语言(Unified Model Language,UML)在创建模型的时候广泛使用,很流行。

但是这种语言也存在一些限制,例如,当你有一份绘制了成千上万个类的文件的时候,很难表示类之间的关系,也很难理解它们的抽象性的同时理解它的含义。此外UML关系图也不会表示模型的概念以及对象都应该做什么;

文档和代码也是沟通领域模型的方法之一;

2.多层架构

多层架构是DDD的一个通用解决方案。它包含四个层次

这种分层的架构非常的重要,它使得领域相关的代码与其他层分开;

在这种多层架构中,每层都包含其各自的代码,这有助于实现松耦合并避免把不同层的代码相混合,还有助于产品/服务的长期可维护性和增强功能的方便性。

使用多层架构,每一层都可以很容易的使用另一个实现来切换;

1.表示层

此层表示UI,并为交互和信息展示提供用户界面。这一层可能是一个web应用程序、移动应用或者使用你服务的第三方应用程序;

2.应用程序层

此层负责应用程序逻辑。它维护并协调产品/服务的整体工作流,它不包含业务逻辑或者UI,它可以保持应用程序对象状态,如执行中的任务的状态。

例如,产品中REST服务将是应用层的一部分;

3.领域层

领域层是非常重要的一层,因为它包含领域信息和业务逻辑,它保持业务对象的状态,它持久化业务对象的状态并将这些持久化的状态与基础设施层进行通信;

4.基础架构层

这一层向所有的其他层提供支持,并负责向其他层之间通信。它包含由其他层使用的支持库,它还实现了业务对象持久化;

3.领域驱动设计的工作

在DDD中存在用于表示、创建和获取领域模型的不同工件;

1.实体

在产品中创建实体是指创建标识符;

为对象创建一个唯一的标识符有不同的形式:如下所述:

使用表中的主键;

使用领域模块自动生成的ID。领域程序生成标识符,并将它分配在不同层间被持久化的对象;

少数现实生活中的对象本身就是自带用户标识符。

一个属性或者属性的组合可以用于创建一个标识符。

在建模的初始阶段就应该定义实体;

2.值对象

实体具有一些特征,如身份、连续性的线程以及不能确定其身份的属性。值对象(Value Objects,VO)只是具有属性,而没有概念上的身份。

应用程序不总是需要有一个可识别的客户对象并加以追踪,有些情况下,只需要有领域元素的一些或者全部属性。这些都是可以由应用程序使用值对象的情况,它使得事情变得简单,并且提高了性能;

由于不存在身份,值对象可以被方便的创建和销毁;

如果你需要此VO的一个不同的值,或其任何对象,那么只需要创建一个新对象,但是不要修改原始的值对象。

3.服务

在创建服务的时候,需要注意以下几点:

如果在创建领域模型的过程中,你可能会发现不同的不属于任何特定对象的行为或者方法。这些行为是重要的,又不能被忽视,也不能把它们添加到实体或者值对象中,把行为添加到不属于它的对象中会破坏次对象。请记住,那些行为可能影响各种对象。使用面向对象编程可以将它们附加到一些对象上,这就是所谓的服务;

服务在技术框架中是常见的,这些也都用在DDD的领域层中。服务对象不具有任何的内部状态,它的唯一目的是提供针对领域的行为。服务对象提供不能与特定实体或者值对象相关联的行为,可能会为实体或者值对象提供一个或者多个相关的行为。这是在给领域模型中显示定义的服务的做法;

  1. 在实体和值对象上执行的服务对象的行为,但是它不属于实体或者值对象;
  2. 服务对象的行为状态不会被保持,因此它们是无状态的;
  3. 服务是领域模型的一部分;

4.聚合

聚合域模式与对象的生命周期相关,并定义所有权和边界。

关系、约束和不变量带来的复杂性需要在代码中进行有效的处理。我们利用由称为根的单一实体表示的聚合来解决这个问题,根与数据更改的时候用来保持一致性的一组对象相关联;

根是唯一可以从外部访问的对象,所以此根对象充当内部对象与外部世界分离的边界的大门。根可以引用一个或者更多的内部对象,并且这些对象内可以引用其他内部对象,而这些内部对象与根之间可能有关系也可能没有关系。然而,外部对象也可以引用根,但是不能引用任何内部对象;

聚合根实体保存其全局身份并保存其各实体内的本地身份;

在餐馆订座系统中,聚合的一个简单例子就是客户。客户可以接触到外部对象,并且其根对象包含其内部对象的地址和联系信息。当发出请求之后,就可以把诸如地址等内部对象的值传递给外部对象;

5.存储库

存储库是与基础设施如数据库或者文件系统进行交互的地方。存储库对象时领域模型中与诸如数据库、外部来源等存储区(storage),以检索持久化的对象进行交互的一部分。

存储库与基础设施层交互,此接口是领域层的一部分。

存储库帮助系统来管理领域对象的生命周期;

6.工厂

当一个简单的构造函数并不足以创建对象的时候,就需要用到工厂。它有助于创建复杂的对象或者一个涉及其他相关对象的创建的聚合;

工厂也是领域对象声明周期的一部分,因为它负责创建它们。工厂和存储库以某种方式彼此相关,因为两者都引用领域对象。工厂引用新创建的对象,而存储库从内存中或从外部存储器中返回已经存在的的对象;

7.模块

模块是分离相关业务对象的最好方法。这些都是最适合于领域对象的规模更大的大型项目。对于最终用户,把领域模型划分为模块并设置这些模块之间的关系式有道理的。

模块还有助于产生很高的内聚或者保持低耦合的代码。普遍存在的语言可以用于命名这些模块。

对于餐馆的订座系统,我们可以拥有不同的模块,如用户管理、餐馆和餐桌、分析和报告,以及评论,等等;

4.战略设计和原则

企业规模很大和复杂的情况下,大型企业规模需要被划分为不同的子模型。这些子模型包含预定义的准确关系和具有微小细节的合同。每个子模型都必须无一例外的保持既定的合同;

保持领域模型的完整性有各种可以遵循的原则,如下所示:

  1. 有界上下文
  2. 持续集成
  3. 上下文映射

共享内核

客户-供应商

顺从者

反腐层

各自的方法

开方主机服务

精馏

1.有界上下文

模块是有界上下文的一部分,它定义了子模型产生并被开发的逻辑框架。而模块组织领域模型的的元素,并可以在设计文档和代码中看见;

每个领域模型都有其有界的上下文,需要确保它们之间的接口正常工作;

2.持续集成

在持续集成中,经常合并代码以避免造成任何破坏和领域模型的问题。合并的代码不仅得到部署,而且还被定期测试。

市场上有能够在预订的时间合并、构建和部署代码的各种持续集成工具。现在,各个组织更加注重持续集成自动化。Hudson、TeamCity和JenkinsCI是现在可以用来进行持续集成的几个流行工具。Hudson和Jenkins CI是开放源代码的工具,而TeamCity是一个专有的工具;

每个生成版本都具有附加的测试套件来验证模型的一致性和完整性。测试套件从物理的角度定义模型,而UML则在逻辑上定义模型。它告诉你有关任何错误或者意外的结果,需要更改代码来改正它们,还有助于及早发现领域模型中的错误和异常;

3.上下文映射

上下文映射帮助你理解一个大型企业应用程序的整体情况,它显示在企业模型中有多少有界上下文存在,以及它们如何相互关联。因此我们可以把任何解释了有界上下文和它们之间关系的关系图或者文档都称为上下文映射;

下面就是用来定义上下文映射中的不同上下文之间通信的模式;

1.共享内核模式

一个有界上下文与另一个有界上下文共享一个部分;

2.客户和供应商模式

一个上下文把信息提供给其他信息的使用者(称为客户)

3.顺从者模式

不同于有界上下文,实际参与的团队有上下游的关系;

如果供应商提供的信息不足,任何一个客户团队都可以开发他们自己的模型。

4.反腐层

反腐层仍然是领域层的一部分,当系统需要从外部系统或者从他们自己的遗留系统获取数据的时候,就会用到它。在这里,反腐层是与外部系统进行交互,并在领域模型中使用外部系统数据,而不会影响领域模型完整性和独创性的一个层;

大多数情况下,可以使用服务作为反腐层,它可能使用具备适配器和翻译器的外观模式在内部模型内使用外部领域数据。因此,你的系统始终会使用服务来获取数据。服务层可以使用外观模型设计。这将确保它将与领域模型配合工作,以按照给定的格式提供所需的数据。然后,服务还可以使用适配器或者翻译器模式,这将确保无论是由外部来源发送的数据格式和层次结构是怎样的,都将使用适配器和翻译器提供所需的格式和层次结构的服务;

5.独立方法

独立方法就是指把多个能够独立开展工作的大型子模型继承为一个独立的应用程序提供给用户使用;

工作单位内部网应用程序是这类应用程序中的一种,它提供如人力资源相关、问题跟踪器、运输或公司内部社交网络的各种小应用程序,设计师可以使用独立方法的模式开发它。

如果要集成使用独立模型开发的应用程序,这将具有非常大的挑战性和复杂性。因此,在实现这种模式之前,需要三思而行;

6.开发主机服务

当两个子模型彼此交互的时候,就会使用翻译层。

这个翻译层用于把模型与外部系统集成;

开放主机服务使用对所有子模型的包装提供外部系统的服务;

7.精馏

精馏是过滤掉不必要的信息,并只保留有意义信息的过程。

它可以帮助你识别核心领域和业务领域的基本概念,过滤掉一般的概念,直到你得到代码域的概念为止;

比如餐馆定座系统中,它不是一个大型或者复杂领域的应用程序,它的核心领域就是为了共享实时准确的在餐馆里面的空闲餐桌,并允许用户以不麻烦的过程来预定它们;

5.示例领域服务

基于领域层开发项目有更好的可维护性、高内聚性和解耦性。

它们在业务需求变化的时候能够提供高可扩展性,并对其他各层的设计有较少的影响;

领域开发基于领域,因此不推荐你使用首先开发UI,紧接着开发其余的层,最后开发持久层的自顶向下的方法,也不推荐开发类似数据库的持久层,然后开发其余的层,最后开发UI的自低向上的方法;

首先确定一个领域模型,将使得所有团队成员对功能都有清晰的认识,便于软件师来建立一个灵活的、可维护的、一致性的系统,可以帮助组织以较低的维护成本来开发世界一流的产品;

接口隔离原则:客户不应该被强迫去依赖于他们不使用的接口;

1.实体的实现

2.存储库的实现

3.服务的实现

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值