DDD(一)微服务、领域驱动设计、领域模型

什么是微服务

单体结构项目

image-1660404526945

优点:结构简单,部署简单等

缺点:耦合;技术栈统一,软件包版本锁定;一崩全崩;升级周期长;无法局部扩容;

微服务结构项目

image-1660404555977

优点:耦合性低,易于开发和维护;可以用不同技术栈;可以单独扩容;互相隔离,影响小;部署周期短;

缺点:对运维能力要求高;运行效率会降低;技术要求高,需要处理事务最终一致性等问题。

微服务的误区

image-1660404578375

微服务架构应该是进化而来的;微服务的拆分进化。(项目起步应该拆分的服务很少可能只有2 3个,慢慢的随着系统业务越来越庞大,慢慢再拆分)

在设计不好的微服务架构中,微服务之间的调用关系非常复杂,一个来自客户端的请求甚至要经过七八层的微服务调用,这样糟糕的设计不仅导致系统间耦合严重,而且使得服务器端的处理效率非常低。

在项目初始阶段,需要认真思考,我们是否非用微服务不可,并拿出充足的理由。不要为了微服务而微服务。

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

1、是一个很好的应用于微服务架构的方法论。

2、在项目的全生命周期内,所有岗位的人员都基于对业务的相同的理解来开展工作。所有人员站在用户的角度、业务的角度去思考问题,而不是站在技术的角度去思考问题。
3、诞生于2004年,兴起于2014年(微服务元年)。

例如:当我们需要开发一个电力系统的时候,我们可能需要了解电力相关的知识或者说成为一个电力专家,当我们开发一个金融系统的时候,我又要成为一个金融专家等等。成本很高。而且我们只开发系统,也不需要成为每一个领域的专家。

4、DDD晦涩难懂,难以落地。因为DDD是方法论,不是行动指南。
5、“盐少许、油少许“,每个人对DDD的理解和落地都不同,而且没有绝对的对错。
6、如果只学习DDD概念而没有了解如何应用的话,会感觉没有落地;而如果过早关注落地的话,会导致理解片面。

7、正确姿势:“从理论到实践,从实践再到理论……”
我的讲课顺序:把概念的讲解和技术落地分开。Why?
8、不要一下子学DDD的整体。不同岗位、不同阶段的人先从自己的角度学习DDD的一部分。

领域

1、“领域”(Domain):一个组织做的事情。子领域。
2、领域的划分(以手机公司为例):
核心域:解决项目的核心问题,和组织业务紧密相关。
支撑域:解决项目的非核心问题,则具有组织特性,但不具有通用性。
通用域:解决通用问题,没有组织特性。
3、领域的不同分类决定了公司的研发重点。

领域主要指一个组织做的所有的事情,但是一般为了缩小讨论的范围,会划分为多个子领域。

例如:手机公司

image-1660404603336

手机研发子领域、手机制造子领域解决了手机的核心问题。

销售子领域、财务子领域、售后子领域这些都和手机相关,比如销售手机和销售电脑、销售房子需要掌握的业务知识不一样。属于支撑域。

保洁、保安统称后勤子领域、人事子领域这些领域属于通用域,手机研发公司的后勤和电子厂的后勤做的事情都是一样的。一般这种领域可以外包给第三方。

不同的组织也会导致划分的结果不一样,这里我们就用不同的公司来代替

比如上述说的外包第三方公司,但是对于保洁家政等公司来说,保洁、保安子领域又属于核心域。

总结

手机研发子领域、手机制造子领域为核心域

销售子领域财务子领域、售后子领域为支撑域

保洁、保安统称后勤子领域、人事子领域为通用域

书中销售子领域划分为核心域,但是视频里面没有明确讲销售子领域划分,我个人认为销售子领域为支撑域,如果从利润角度来划分,它又不得不为核心域,毕竟手机造出来卖不出去,没有收入,一切都是空谈

总之,同样的领域由于划分的不同结果也不一样。根据自己的公司来具体划分。

领域模型(Domain Model)

1、对于领域内的对象进行建模,从而抽象出来模型。

2、以银行为例。

​ 银行的柜台业务领域中,就有储户、柜员、账户等领域模型。建模是DDD中非常核心的事情,一旦定义出了领域模型,我们就可以用领域模型驱动项目的开发。

3、我们的项目应该开始于创建领域模型,而不是考虑如何设计数据库和编写代码。使用领域模型,我们可以一直用业务语言去描述和构建系统,而不是使用技术人员的语言。

事务脚本

使用技术人员的语言去描述和实现业务事务。没有太多设计,没有考虑可扩展性、可维护性,流水账地编写代码。

例子:

image-1660404624162

总结:这样的代码

优点:编写简单,自然,非常符合开发人员的思维方式。

缺点:事务脚本中,本该属于支撑域的权限的概念出现了再核心域的代码中,我们应该通过AOP(aspect-oriented-programming,面向切面编程)等方式把权限校验的代码放到单独的权限校验支撑域中。这段代码的另外一个问题是,对于需求的快速变化的响应是非常糟糕的,比如系统的需要增加一个“取款金额大于5万的需要主管审批”的功能,我们可能需要对代码进行增加一个if判断,,或者系统增加一个取款成功之后短信的通知等等,随着系统的业务膨胀,上述Withdraw方法会增长到成千上万行,代码的可维护性可扩展性非常差

DDD通用语言、界限上下文

1、“我想要商品可以被删除”→“我想要把删除的还原回来”→“Windows回收站都能”
2、此“用户”非彼“用户”。
3、通用语言:一个拥有确切含义的、没有二义性的语言。

4、通用语言离不开特定的语义环境,只有确定了通用语言所在的边界,才能没有歧义的描述一个业务对象。

为什么使用DDD(领域模式):https://juejin.cn/post/6895096192980484103

领域驱动设计(DDD)在爱奇艺打赏业务的实践:https://juejin.cn/post/7050738599649607694

CQRS Journey:https://docs.microsoft.com/en-us/previous-versions/msp-n-p/jj554200(v=pandp.10)

DSL 领域特定语言 :以上相关博客或者书籍有时间可以自己了解和查阅。

DDD之实体、值对象

实体(Entity)

1、“标识符”用来唯一定位一个对象,在数据库中我们一般用表的主键来实现“标识符”。主键和标识符的思考角度不同。
2、实体:拥有唯一的标识符,标识符的值不会改变,而对象的其他状态则会经历各种变化。标识符用来跟踪对象状态变化,一个实体的对象无论怎样变化,我们都能通过标识符定位这个对象。
3、实体一般的表现形式就是EF Core中的实体类。

值对象(Value Object)

1、值对象:没有标识符的对象,也有多个属性,依附于某个实体对象而存在。比如“商家”的地理位置、衣服的RGB颜色。
2、定义为值对象和普通属性的区别:体现整体关系

总结:

核心是看是否能自己独立存在

能就是实体,否就是值对象

例如

身份证ID不会变 但是年龄、姓名、居住地址、有效期等等都会变化,由于身份证ID没有变,这个人(对象)还是之前的那个人(对象)。

反过来就算年龄、姓名、居住地址、有效期等等都一样,但是身份证号不一样,那也是2个不同的人(对象)

本文内容大部分都为杨中科老师《ASP.NET Core技术内幕与项目实战》一书中内容,此文只是做学习记录,如有侵权,联系立马删除。