00:00
活动呢正式开始,欢迎大家来到云原生开发挑战赛的第二场直播现场,本次大赛呢,是微软20周年的特别活动啊,给大家简单介绍一下我们此次大赛的一个赛事流程跟奖项,大赛呢截止日期是在6月15日,此次大赛呢。的参与方式呢非常的简单,可以通过第一是个人原创作品,第二是参赛的作品呢,要求后端为点技术的完整项目,并且上传至51AS PX平台,那大赛呢,将会组织微软专家在线进行培训讲解,并按照创新、实用、完整度等几个维度进行评分。并且呢,此次赛事呢,奖项丰厚,那具体的赛事规则呢,请大家扫描一下屏幕当中的二维码进行咨询了解。此次大赛的主办方呢,是由微软以及51AS spx平台呃共同主共同主办,那51AS spx是国内首个点ne交流交易赋能平台,并且呢,此次大赛的战略合作伙伴呢,有微软MVP团队,微软社区以及集湖gileb。微软MVP团队为本次大赛呢大赛的直播课提供了大量的讲师,微软reactor社区作为本次大赛的社区支持方,GI为本次大赛呢提供源码托管服务。
01:35
好,给大家简单介绍一下此次直播课的一些信息,首轮直播课呢,我们邀请了业界的四位大咖进行五场实战直播,今天呢是第二场直播,大家可以关注公众号51AS PX进行呃,了解直播的一些信息,并且呢可以扫描一下屏幕当中的二维码进入到我们的直播社群抽奖,以及我们会在课后呢,会将我们的讲师拉到我们的社群当中给大家进行一个答疑,我们的直播课呢,会在CSDN私否哔哩哔哩,腾讯会议以及微软。
02:15
和51PX的视频号上同步直播,那么最后呢,给大家隆重介绍一下今天直今天直播课的讲师杨中科老师,杨老师呢是微软MVP传播者,全网30万粉丝,有零基础去学C语言。自己动手写开发工具等书籍,并且呢,在今年的五月份呢,即将要出版ASP点扣内幕与项目实战,那么接下来呢,就请我们的杨老师为大家进行今天的直播课。杨老师。啊。好。我把屏幕交给你。
03:01
啊,行。呃,可以看到我的屏幕吗?可以,OK,那好,呃,那我就开始了啊呃首先感谢各位朋友来参加这次直播的活动,呃,这次直播的活动叫做云原生开发挑战赛,呃所谓的云原声啊呃每个人有不同的理解,但呃我说在云原声中必不可少的一个技术,那一定是这个微服务这个技术,因为所谓的云原生值就是咱们的应用从开发的时候我就说它一定是部署到云上的,甚至整个的开发,从开发的时候,整个的开发的这个环境都是在云上的,那么在这样一个云原生的开发环境上面,那么这个微服务可以说是不能说我必须得选,我不用这个微服务技术,我也可以进行原云原生的开发,但是95%甚至99以上的云原生应用都是这个基于这个微服务的基础的,OK,所以说。
04:05
呃,云原生相关的技术,那就是这个微服务,那和微服务相关的非常重要的概念是这个ddd,所谓的这个领域驱动,这个这怎么翻译成中文,还不是翻译什么domain driven design是吧,领域驱动设计OK,那么呃。呃,当然其实这个ddd也并不是专门为这个微服务而生的,那么一会儿我会讲这个D,这个ddd其实早于微服的概念而生,但是它真正兴起来的时候,是在这个微服务兴起来之后,Ddd的概念才这个焕发青春的,那么因此我在这儿来给大家去分享一下这个ddd这个概念其实也是属于咱们云原生中非常重要的一个进行系统的这个设计啊,系统实践的这样一个非常重要的理念,我来给大家去分享,那么。呃,刚才主持人也说了啊,在这也给加了点私货,就是我大约五今今年五暂的会出本这样一本这个S岁刚才靠的这个呃书籍,那么这个书籍里面有这个实战的内容,那么我这个书中这个D滴D的内容也是非常重要的一个章节,呃,欢迎到时候大家进行这个关注,但是现在还没出版呢,大约五月份来进行出版。那么什么叫做ddd,呃,Ddd这个全称叫做领域驱动设计,它的关键词叫做设计,所以说呃,其实DD它并不是一个纯的技术的名词,现在很多的这个人,特别是很多程序员一去学ddd就把它当成一门技术去学,那这样的话你越学越走向牛角尖,那么ddd它具体实现的时候,肯定会有技术去实现,但你开始去了解的ddd的时候,先要站在设计的这个角度去思考,这样的话你才不至于迷茫,说这玩意儿是什么东西是吧?所以说先知道它是一个解决软件设计的这样一个。
05:57
的东西,然后你才不至于让自己思维立即细化到说,哎,这玩意儿怎么在编程,怎么去实现,因为咱们程序员这个最容易说接到一个东西就说,哎,这个东西编程怎么做啊,用哪个类,用哪个包,我能不能找到一个包叫做滴滴D的包,我能不能找一个框架叫做滴D的框架,最后找下来之后发现自己一头雾水,因为从来就没有一门技术叫做ddd啊,Ddd它是用来指导设计的啊,咱们程序进行实现的时候,只是对于它设计理念的一种应用,一种实践而已,所以说先先要明白它是怎么一个东西。
06:34
那么ddd它既然是一种设计的理念,因此啊,它是可以应用于咱们整个软件项目的全生命周期的,也就是说无论是从这个公司的股东、老板,项目经理,甚至包括测试人员,甚至包括客户开发人员,这个产品经理。所有的岗位的人,哪怕包括DBA,哪怕包括运维,都要着这个ddd,都应该是指导他们的工作,OK,而不是说只是把滴滴的工作扔给开发人员,那这个也是错了,他是用来指导整个项目中所有涉及到的这个人员的工作都涉及到,甚至我说公司里边的保洁都应该把ddd把它参与进来,这句话绝对不是开玩笑啊,你真正把这个DD的理解的话,保洁的工作你给他安排好,也是一种ddd理念的一种体现,OK,那么。
07:25
呃,这个ddd,呃,每个人有不同的理解,我在这儿必须去说啊,呃,如果说在这个软件开发这个这个领域啊,要引起引要引起这个骂战,有两个技术,有两个话题可以引起骂战是吧?一个话题是哪个编程语言最牛是吧?这个do奈和Java Java和PP掐,总是掐来掐去,很开心,这个群群里边掐起来了,那么关于ddd啊,这其实也是一个容易掐起来的一个点,我在网上发表一篇文章,谈谈我对于滴滴滴的理解,另外一个跟过来肯定啊,你这说的什么玩意儿,那不行不行,我这才对啊,大家说哇,这是牛人,他好像说的挺有道理。另外又过来一个人,你说的什么呀,你说的全错了,我说的才对,你会发现啊。
08:10
整个这些人聊下来之后发现啊,每个人对于滴滴滴都有了解,但是好像有时候两个人的观点还是矛盾,是对立的,我不知道该听谁的,那么这也是一个滴滴的一个非常,呃,非常这个难以掌握的地方就是说不同人有不同的理解,有不同的实现,呃,很多时候啊,这些不同的理解并没有一个谁对谁错,所以这就是滴滴最难以理解的地方,所以说我在这啊,这次直播我只是分享一下我对于滴滴的理解,可能别人也有他自己的这个理解,那么咱们进行商量,OK,但并不是说因为说我这说的这个东西怎么怎么样,咱去这个讨论去商量,并不是说你的错我的对,也并不是说我的对你的错,咱们这个站在不同的角度,站在不同项目里边都有不同的理解,这玩意儿是最恶心的一个东西,OK,刚才我提到了,说咱们这个滴滴的概念啊,最开始其实诞生于2004年。
09:06
但是之后的十年间,基本这个东西只停留在论文这个层面,只停留在这个,呃,这个。这个,呃,这个讨论中落地并没有非常好的落地,直到2014年,所谓的叫做微服务,原因就是2014年的开始。各个公司都开始提起了微服务这概念,然后D滴的概念才重焕青春,因此ddd并不是为微服而生的,但是DD因微服务而发光发热,所以说我可虽然说这个先后顺序不对,但咱们可以说是ddd就是一个什么指导微服务架构的这样一个非常好的一个理念,呃,刚才我也提到说吧,Ddd这个概念特别晦涩难懂,而且你也不知道怎么去落地啊,因为DD它不是一个具体怎么去做的一个东西,这就像咱们这个中文。
10:00
咱们这个这个中餐是吧,做饭经常说是盐少许油少许。这个。这个炸什么东西的时候要微热啊,用手背贴的时候感觉它啊微微发烫,就可以扎这个鱼了,那什么叫做微微发烫啊,什么叫做盐少量有少量,这玩意儿没有一个很定量的标准,而不像说像这个,比如说麦当劳,肯德基炸那个炸鸡,那肯定都是看那个温度计,比如到200多少度的时候放炸鸡是吧,炸一分半钟啪就拿出来,非常精准,那么这就中餐和这种西式快餐搭葡萄一样,一个地方,那么D滴D也是如此,D滴D很多的很多的概念,它只是说建议这样做,应该这样做。但是他没有说具体必须得怎么做,你就像编程一样,我这个int类型的变量,你给他复制一个字符串肯定不行,对不对。但是在BD这个领域,它就没有这样一个非常死板的规矩,所以说让你嗯感觉云里雾里。
11:02
那么这时候呢,而且大家学DD的时候啊,有一个问题就是说太过早关注这个ddd的概念,你翻那个关于DD原始那个论文去是吧,你会发现。说的什么呀,是吧,你就会发现这感觉跟看无字天书一样,你也不知道怎么去应用,但是如果说你过早拿出来一个说啊某个框架,这个框架是这个基于DD的理念的,你去研究这个框架,有时候反反而会导致说你对于ddd个概念还没有一个整体的理解过早。这个这个这个埋头于实现的话,你就缺少了一个先对于DD的整体一个了解这样的过程,所以说大家学习地的时候,应该先整体对整个的概念有一个模糊的了解,模糊的了解即可,不可能完全搞明白,但是对整体的结构,整体的概念有个模糊的了解之后,再去关注这个落地技术会搞一些好一些,所以说这也是建议大家去学习DD的时候的一个。正确的姿势是从理论到实践,从实践再回到理论,这是什么意思呢?就是说你学习DD的时候,先把那概念看一遍,别管看得懂看不懂,先看一遍,然后你再具体,哎,看我这个具体一个ddd这个实现的一个,在我这个代码这个层面怎么去实现,因为ddd不止于代码,我说过了,老板怎么安排公司的工作,老板怎么进行这个公司部门的划分。
12:23
OK,这个都是有ddd可以来做指导的,我不去谈那些东西,我只谈在代码这个层面上,那么咱们了解这概念之后,就去看一看,哎,我这个代码怎么去应用。我们应用完之后呢,回过头来对于这个D滴有更深入了解之后,你回过头来再看理论哦,发现之前对这个理论不理解地方更深入了,回过头来再去,呃,再去实践,实践完之后再回到理论,它是一个反反反反复复这样一个过程,OK,所以说大家学习滴滴的时候呢,也不要一次学整体的一个概念,其中有很多的概念啊,他是不是给咱们程序员用的,OK,他是给老板用的,它是给这个产品经理用的啊,不一定全部都是给程序员用的啊,那不同岗位的朋友来了解ddd的时候啊,侧重于对于自己的这个。
13:11
领域的相关的概念进行了解就可以了,OK。所以说千万别一下子学整体都学整体学完你就根本就不知道他在学的啥,那么啊,最后这我在这列这么一张图是吧,这也是很多人学地弟的时候,就和学这个叫什么道德经的时候一样,道德经说的是道和道非常道,名可明非常明,无名天子之是有名万物之母,这说什么玩意儿,是不是那么,哎,这就像当年我上大学的时候吧,我第一次看道德经,我就是感觉他说的这好像是,这好像是我未来几十年的这个人生道路应该怎么走,那工作几年之后呢,我再去看道德经,我就感觉说啊,他好像是在说的是这个艺人在公司里边怎么样的,来这个跟同事啊,跟领导啊怎么相处,后来呢,我自己创业,我感觉嗯,这好像是和公司的这个发展和公司管理有关系,后来呢,我有了孩子,我想哎,好像这玩意儿对。
14:15
对儿有帮助,你会发现啊,对道德经这样一个概念东西,你在不同阶段理解都是不一样的,但是你一开始看的时候也是云里雾里,所以说道德经,道德经这个概念它有两个层面东西,第一个是你刚接触时候感觉云里雾里,这是第一个云里雾里,这是大家和接触ddd也是一样云里雾里,这很正常,第二你慢慢理解了一下之后呢,你在不同的阶段对于这个ddd也是有不同的理解的,这非常正常,我现在我在这这个。给大家大言不惭的给大家去分享ddd,那可能五年之后我再回过头来看,现在我讲讲东西,可能我会发现说,诶,我那时候对于这个DD又有新的理解,那么这个ddd一个非常这个玄妙这个东西OK。OK,那么咱们开始进入正题,先来谈一谈啊,当然ddd的概念非常多,我在这儿只是覆盖几个对于咱们技术人员比较重要的几个概念,整体我我没有时间给大家展开去讲。OK,那么。
15:14
看下时间,别超时了,那么首先来谈第一概念,叫做这个聚合。呃,当然其实在这之前应该谈谈什么叫做领域,因为领域驱动设计现在谈领域,但是呃,这个我一会儿后边会给大家去给一些大家关于什么领域啊等这样一些其他概念的所有的一些相关资料,我在这儿先给大家讲这些对于技术人员最重要的概念,好吧,那么首先来讲一下什么叫做这个聚合。大家作为程序员都明白概念叫做高高内距低耦合是不是,什么叫做高内聚低耦合,高内距指的是说一个零件,一个组件内部非常充分的在工作,谁都不闲着,谁都在发挥着自己的能力,叫做高内聚低耦,何止是说这些零件之间进行这个协作的时候,呃,这个非常。
16:06
非常好的协作在一起,不乱套,这叫做高那聚低耦和,那你说这个家庭里边,呃,一家一家五口人,另外四个人在这个非常忙的,这这个收拾家务,这个做饭,另外一个人在那闲着耍手机,那这个家庭就不高那句因为有一个人闲着是吧,OK,那你说这个deal什么叫做这个。何呢是吧,咱们家和别的家咱们说连起来,这个一起办个家庭party。然后这个合作的乱七八糟,呃,这个整个把party搞乱了,那么这叫做这个耦合性不好,因为这个乱套了,OK,所以的高内句低耦合,就是说我一个组件内部啊,啊这个这个谁都必不可少,谁都很通过的在工作,低耦合只是说这个组件内部进行沟通的时候,条理非常的清晰,不乱套,OK,这个叫做高内句低耦合,那么具体到咱们的编程实现的时候,这个高内句低耦合,那所以聚合,聚合,就这俩字,聚。
17:08
合啊,所以说聚合体现的一个聚一个合,那么体现在咱们编程上,其实指的主要指的是说咱们编程中的一个实体的一个怎么样的一个设计。什么样实体,大家无论用过什么orm是吧,无论是这个我靠或者老的EF,或者说这个什么什么什么别的什么diaper啊之类的,无论都什么呀啊,这些OM里面都有非常重要的概念,叫做实体,实体就是一个类是吧,咱们在这个实体里边说通俗一点啊,说通俗一点你看咱们在实体里边。咱们这个。建一个棚子。是吧,P你扭一个person来,那么在这里边儿你A值等于五啊这个。Name写错就写错了啊,就那么个意思就得了YZK,然后最后你一个OM这个SAVE1保存进来就保存到数据库了,不是咱们这个person,它就是一个实体类对不对,那么我这个聚合解决的就是说在咱们这个系统中。
18:13
这些实体怎么样去设计,因为大部分业务系统最终非常重要的资产就是你的实体,实体反映得到,就是你这个数据在数据库里边怎么所以说。实体非常重要,那么怎么样的设计实体,这是聚合所考虑的问题。有同学说这个有什么考虑的,我表怎么设计,我这个实体就怎么搞呗,我这个表有八个字段,我这个person类就有八个字段,就得就八个属性不就得了吗?如果说你是先设计表,再反过来生成这个实体,那么你这是一个。非常不好,不能说不对啊,我在这儿没有说不对,因为任何做法都是有它合理的地方,OK,你说这个。喝脏水行不行?喝脏水绝对不可以,但在某些场景下,喝脏水就是对的是吧?比如说你你吃了有毒东西,喝脏水你催吐是吧?咱不去说这些特殊情况,对大部分情况来讲,喝脏水是有错的,对不对?同样的,对于咱们的这样一个开发来讲,大部分情况下先设计表,再来设计实体,这是错误的,这叫做数据库驱动开发。
19:22
数据库驱动开发这样大部分情况是不好的,好的情况特别在DVD中推荐什么叫做模型驱动?就是说我来设计模型,模型最终由数据库怎么去实现,这个是稍后考虑的事情,我先考虑我的模型怎么做,怎么做最符合我的语义,然后我设计这个模型,具体在数据库怎么去实现,我稍后再考虑,OK,所以这个模型驱动,那么正是因为这个模型驱动中,我这个实体类怎么设计非常重要,所以说聚合体验,就是说咱们怎么样来设计这个实体类。啊。呃,设计的一个基本的原则,也就是说。
20:04
不是想咋设计咋设计,而是要把其中一个实体作为聚合根,所有的对于这个我这个聚合内的其他实体,也就是说我这个实体类管理的多个。一个或多个实体,所有对其他实体的操作都通过我这个聚合根来操作,在这说的有点抽象啊,说一个通俗的例子,就是说,比如说咱们说一个订单和这个订单明细。那么他们就是一个聚合的关系,一般来讲都是一个聚合的关系啊,那么我比如说我给这个订单增加一个订单项,增加一个订单明细,我都是通过订单实体来做的,而不是我直接一个order item,而是我通过它来增加一个订单项,我删除一个订单项呢,也是通过它来进行,而不是我直接NEW1呃这个这个从这个order items里边,比如说你直接这个。Order,这个这个order点2ITEMS remove,这样做是不好的,你直接把它从它的items里边把某一项给它删除,这样是不对的是吧,包括你添加一项,这么添加也是不对的。
21:11
OK,都是不对的,为什么呢?因为你这是。没有通过它来进行,当然有人说认为这也行啊,但是更好的方式怎么样呢?更好的方式,比如说我在这order ADD这么做。那其实我这at it里边其实就是封装那个it点艾,好像没什么区别,但是就这样去写的话,我的这个聚合根就负责管理了这个我这个聚合根里边所有的实体,这样带来的好处就是说我的这个聚合根了解我所管理的所有的这个实体的一个状态,这样的话进行状态的这个更新状态的管理的时候就更加清晰,而不是各个这个,呃,这个其他的实体乱动我都不知道,这样就乱套了啊,得有一个或都一个车头带着他们走,OK,这是关于咱们聚合设计的一个非常重要的概念啊。那么。
22:01
当然这个不同的业务流程也决定了不同的划分方式,并不是说啊,像这种明细结构一定是这个。呃,Order是,就是这个主是聚合,根子是它里边的这个聚合实现的,比如说我这讲这个,举这个例子,就是说这个新闻和新闻的评论在场,在我这个场景下,好像我这个新闻的评论。属于这个新闻的这个聚合里边的一个实体,对不对?可以这么设计,但是也可以把这个新闻和评论设计成两个这个聚聚合,这样的做的好处是什么呢?我的新闻可以单独出现,比如说网站有一个这个热辣新新闻,这个这个评论榜,或者说说新闻和新闻的评论,我的评论可以单独出现。啊,这个最佳评论吧,最佳这个这个神回复,那么这样的话,他的这个评论可以单独出现,那么这种情况下哈,咱们的这个新闻和新闻的评论可以作为两个的聚合,OK,那么进行聚合划分啊,它最大的好处是什么?记住这一点,这点非常重要,那么为什么要进行聚合的划分?
23:07
聚合划分有助于进行服务的。拆分注意,微服务并不是一蹴而就的,很多人用微服务啊,最大的一个误区就是本来项目没多大,咣咣咣拆出168个微服务来,最后发现自己都管理不过来了。真正好的微服务设计可能一开始就一两三四个微服务是吧,这个不一定,但是微服务数量不会太多,随着系统的进化,它的微服务也拆,诶发现这个到2.0这个版本了,哎,之前的这一个微服务拆成两个吧,到了2.2这个版本了,哎,那个微服务拆成三个吧,它是随着系统的进化,微服务在一直在拆分的,所以说这个拆分不是在最开始定好的,而是后期随着系统进化慢慢进行微服务拆分的,那么聚合的划分是有助于微服的拆分的,那么对于这样一个在同一个聚合内的微服务很难不能说拆分不了,就是说相对来讲很难就拆分了,因为他们是。
24:09
耦合在一起的,但是对于两个聚合进行拆分就很简单,比如说哪天啊,我这网站啊,新这个评论比新闻还火爆,那么我在第一个版本的时候,新闻和新闻的评论我是放到一个微服里边了,当然是在两个聚合中的属于一个。微服务中的两个聚合OK,一个微服务中的两个聚合。后来我评论比新闻还火爆,那么我就咔,因为他们这两个评论和新闻之间的耦合项非常的低,因为他们是放到两个这个聚合中的,所以啪拆分起来很容易。一下就分裂出新闻微服和新闻评论的微服啊,所以这是聚合对微最大的益处,OK,所以说光看动态是体验不出来聚合的好处的,只有在拆分的时候你才能知道聚合有什么好处。
25:00
那么呃,这个第一中另另外重要的概念叫做事件,当事件这个指的是什么呢?指的就是发生某一件事情的时候,执行某一个动作,哎,我在这举这样一个例子。啊,比如说我是做一个这个类似于知乎啊等这样一个网站,那么我用户提了一个问题,那么有人都回复了他的问题,那么我这个需求就是说,当有人回复了某个用户提问的时候,系统呢,就像提问者的邮箱发送一个通知邮件,说哎,有人回复了你的提问,那么如果说咱们通过传统的方式啊,事物脚本,那也是个DD这种的概念,但我现在先不去讲这个什么叫事物脚本,但总之是如果说没有ddd这样一个思考方式在这里边的话,咱们这个代码可能这样去写是吧,我这个保存答案这个方法。是这样去写,首先执行把答案保存到数据库中的操作,然后我获取提问者的邮箱,然后再给这个用户发给给这个人发送一个邮件,告诉他你的问题被回答了,大家是不是。
26:03
很多人是不是都这么写的,是这么写的朋友可以扣个一。是吗?大家不用害羞啊,我也是这么写的。是吧,这实际上是最简单的呀,啊,保存答案的时候保存到数据库啊,取一下这个这个提问者的邮箱是多少啊,然后怕给他发邮件,咱是不是都这么做呀。但是这么做。他的问题是什么?现在看不出任何的问题,挺好对不对。但是。系统的很多问题并不是来自于现在,而是以后。比如说以后。发生啥了呢?第一个问题就是咱们系统代码会随着需求的增加而持续的膨胀。是吧,你看我这是画的一个,网上搜到一幅图片,是不是有一个人盖一个房子,越盖越高,越盖越高,越高越高都盖成这样了,是吧,这个东西。
27:00
一脚一踹就踹他倒下了,对不对。很多人写的代码是不是也是这样啊?运行的很很好,但只要稍微一个风吹草动,系统立即崩溃,是不是这就俗称的史山?那咱们如果说这样去写一个最大的问题,比如说比如说我增加一个新的功能,咱们需要啊,在用户回复答案的时候呢,得检查一下他回复内容有没有违法的内容,如果违法内容呢,咱们先得把这个答案隐藏,并且通知审核人员进行审核。咱们的代码应该怎么改了?啊,就得在保存到数据库之前,或者说保存到数据库之后,在这写一个,呃,调用这个检查内容是否有违规的这样一个代码检查啊,如果有违规再执行一个,把这条数据给他。隐藏掉的这样一个操作,然后呢,再写一个向管理员发送通知,让他审核。对吗?是不是这样去写呀,啊又又个别的需求啊,咔改又别的需求改,就发现保存答案这个代码啊,系统进行到8.0这个版本之后,2000行代码一堆if else1堆else if else1堆,不好循环,最后谁都不敢接手这个代码了。
28:12
这就俗称的祖传代码,大家如果在项目中碰到过这种谁都不敢动的祖传代码的朋友,可以回复祖传代码四个字。对吗?OK,这是一个非常严重的一个问题,第二个问题,代码的可扩展性非常低,比如说咱们把这种说,像用户发送邮件改成发送短信怎么办?咱们是不是就得把这啊改成啪啪注射掉,改成发送短信。而大家都应该知道,编程中有一个非常基本的一个原则,开辟原则,叫做对扩展开放,对修改关闭,也就是说咱们正常来讲的话,增加了新的需求或者修改的需求,应该只是增加新的代码,而不是说对于旧的代码做修改,这个开辟原则,但如果咱们这样做的话,是不是需要经常根据需求的变化频繁的来改,来改现有的这个代码啊,这就不太好了。所以咱们。
29:08
这样做很容易不满足这个开辟原则,那怎么怎么做呢?哎,我在这儿引入了一个叫做事件机制,我这个事件机制呢,代码这样去写,那么在保存答案里边,在这个,呃,保存答案里边,我们。这样去写,首先在这写一个保存到数据库,然后最后一个发布一个答案,已保存这样一个事件。完了,我只是说保存数据库,然后发布事件就完了,另外比如说我要想审核答案,比如审核售后违规,我这个代码呢,监听答案,已保存这个事件。然后这段代码里边呢,在检查售后违规,如果违规的话,隐藏答案,并且让内容审核人员进行审核,而且我让他审核,我这儿不是说真的就给他发个邮件,而是说发布一个内容待审核的这样一个通知,那么这个通知到底是通过邮件给到管理员,还是通过系统的push给到管理员,还是通过短信给管理员,我这儿也不知道会有另外一个代码呢,来检测这个内容待审核的这样一个事件,再来写自己的代码,同样的,比如说我要把这个。
30:14
呃,有人回答你的问题,在这个代码实验呢,我也是监听答案已保存这样一个事件,然后在这儿呢,我再获取的问题给他拿邮箱发邮件,那这样的话你会发现啊,我保存答案代码里边非常简洁,每个方法干自己的事儿,它们之间是通过这样一个答案已保存的事件进行若耦合的一个连接。这样做的好处是什么呢?很显然就是关注点分离,每个代码只关注自己的事情,OK,而且容易扩展,OK,怎么容易扩展?我比如说再来一个,说这个不仅发邮件给提供者,再来一个发短信给提供者,那我再写一个方法,也绑定这个答疑,保存事件不就可以了吗?哎,这个能够理解吗?能够理解的朋友可以回复事件两个字。
31:01
嗯,啊,不好意思啊,我这有点事弄不了,不是等一会儿,等一会儿这个镜头出来了,这个摄像头出来就好。不好意思啊,家里边孩子上上英语课。好,那么接下来这个滴滴有两种事件,一种叫做领域事件,叫做集成事件,呃,领域事件指的就是在一个微服务之内的这个聚合之间的适应传递,那么集成事件呢,就是跨为服务的,这个在这儿呢我就不展开去讲了,这个呢后续我再给大家详详细的这个资料,呃,领域事件,提升事件都必不可少,因为有的情况下,我这个事件领域内部消化完就行了,但有的事件呢,可能是说我要要让别的微服务至少来响应我这件事情,OK。那么另外一个DB中有非常重要的概念叫做充血模型。充血模型那么。啥叫充血模型?这也是啊,很多人可能没有意识到之前写的代码有啥问题,我问大家啊,啊,首先啥叫充血贫血模型有一个呢,充血一个叫贫血。
32:02
贫写模型只是说一个类中只有属性或者成员变量,没有方法,比如说咱写一个类,你看我这儿写一个这个,比如说我这个person类,它就是一个贫血模型,因为它只有类,只有属性。没有别的,比如说没有一个什么别的一个方法,它只有这样一个属性,没有其他的方法,这个叫做贫血模型,而充血模型只是说呢一个内容,既有属性传变量,也有方法。当然我这个定义不是非常的准,只是方便大家理解这个学术化的概念,太抽象啊,我只给大家去讲大家能够理解的概念,那么我在这有这样一个需求,来帮大家理解说什么叫充血,什么叫做这个贫血。首先。我这个需求就是我要定义一个类,这个类呢,保存用户的用户名,密码和用户的积分。啊,那么呢,用户呢,必须得有用户名。而且呢,为了保证数据的安全,咱密码不能明文保存,所以说咱们把密码以这个散列值保存到这个数据库里边,用户初始积分为十分,每登录成功一次奖励五个积分,每登录失败一次扣三个积分啊,大家别管我这需求合不合理啊,我这儿只是假设的一个需求,能听懂吧?
33:17
那么怎么实现这个需求?我相信大家,包括我曾经都这样做过。或者正在,有时候我也这么做。叫做拼写模型的做法,定一个类user类。Username。Password散列值,Credit积分。是吧,咱不管主件那个东西啊,咱们就管咱们关注这几个属性是吧,用户名密码啊,密码的散列值,还有积分。大家都这么设计的吧?那接下来咱们看一个典型的应用场景,我新建一个用户。首先我new一个user,让他用户名为YCK。积分是十分,这初始积分嘛,是吧,新建的用户初始积分是十分嘛,然后接下来我算一下,比如说给他的初始密码是123456,我就计算一下12346的散列值,然后给password hash赋值,然后接下来提醒用户说请输入这个密码,我接下来啊,把用户输入的密码的散列值和这个user中的散列值比一下一下,如果哎,发现相等,我就给它加五个积分,提示登录成功,如果不相等的话,如果发现这个积分少于三,就提示积分不足,无法扣减,否则就是积分减三个积分,提示登录成功。
34:30
大家代码是这样去写的吧。可以吧,我刚才提示了网络情况不佳,可以吗?不卡吗?OK,大家都是这么做的吧?那这么做有一个什么问题?这么做?最大的问题就是。咱们的业务逻辑散落在各处,因为你想想,对于我用户来讲,我这个密码到底怎么存,应该是我这个用户。
35:01
这个实体该考虑的事情。OK,我这个积分增啊减呢,怎么增啊,比如说积分不能少于,不能积分不能为负啊。是吧,这个东西应该是我自己考虑问题,而不应该是别人来定的。是吗?这个最大的问题就是把业务逻辑散落到各地。别的地方比如说要用到这个个密码,比如说有英文另外地码叫修改密码了,那修改密码那个地方呢,也得调用一下哈,Helper这个方法来计算一下它散列值,业务逻辑散落各地。而如果说采用充血模型进行设计,我怎么样来设计呢?我定义这样一个类。User username credit,它们两个都还是这个public,但你注意我这username它是一个get init,也就是说它是一个只读的,因为一个我在我的系统里边用户名。创建之后就不可以改了,这是我的系统的需求啊,你说现在淘宝可以改用户名,咱们另说啊,在我的系统里边,用户名一的创建之后没法修改,我怎么体现这个业务流程呢?我把username设置为。
36:08
这个属性只能初始化的时候,创建以后再也不能可以修改了,然后接下来积分别人不可以改,Private set只能读,这是不是也是一个隐行的应用逻辑,就是别人不能随便改积分只能读积分。另外你看密码的散列值,我不是一个属性,而是一个private字段。这样的话,别人不能随便访问我的函这个散列值啊,这太危险了,对吧,所以把它搞成一个private一个字段,那接下来这一个构造函数创建一个用户,因为我一个用户。创建出来的时候,它一定得有一个用户名,不存在说我创建一个用户,但用户没有用户名这种情况,这个在我系统里边是不可接受的,因此我定义了一个构造函数,接受一个用户名,这样的话,我确保我一个优质对象,只要创建出来它一定存在的一个用户名,并且它的初始积分一定是十,那么我这样一个用户必须得有用户名,并且它的初始积分是十的业务逻辑就固定到了我的构造函数里边。
37:09
OK,接下来我又定义了一个方法,叫做change password修改密码,那么我这个计算密码的散列值的代码,我也是写到了这个change password的方法里边,别人要想改密码,在这直接传明文,123456ABCD都行,那我怎算它的散列值怎么算?用什么算算法算,你别管,你给我,我来算。你看我这还有个小的逻辑,就是密码长度不能小于六,我的业务逻辑也包含到我这个user里边了,其他的我就不再说了,什么检查密码啊,这个扣减积分什么,这些都是一样,我都把我的业务逻辑。封装到了我这个user类中,那么这样一个包含了业务逻辑的实体类,咱们就管它叫充血模型的类。哎。OK,你看包括说我做了一个登录操作,我这次实现你看是不是非常简单了,我另一个用户啊,它用户名是1234,设置它的初始密码为123456,输入密码,我检查一下密码对不对,对的话增加五个积分登录成功,不对的话。
38:11
啊,这缺了一个减积分,忘了写了啊,无所谓,就大概是这么个意思,能理解吧,你看一看这个咱们的逻辑是不是特别的清晰呢?所有那些细节的业务逻辑都封装到了我这个U类中。OK,这就是充血模型,那么呃,充血模型这个并不是说是这个叫做贫血模型,不对,而是说贫血模型会导致你的业务逻辑散落各地,而充血模型保证了你的业逻辑是固定在一个固定的地方的,这个在地中有一个非常重要的概念叫做领域知识。领域。说俗点叫做业务逻辑。业务逻辑就是说这个业务逻辑不要散落各地,而是要固定在一个地儿,这样的话可以起到这个重复使用业务逻辑的一个效果,OK。
39:05
这编程不就是咱编程搞架构不就是为了复用代码嘛,是吧,所以说这个冲写模型非常重要的概念就是复用代码。呃,具体这个。实现啊,具体实现,那么。呃,我这说的是说具体实现,首先咱们所以说滴滴里有很多这个落地实现啊,有很多这个相关的技术领域呢,我在这只说三个。方向,这其实两个,一个是咱们的这个,呃,充血模型怎么去实现,一个是关于咱们事件怎么实现,那充血模型的实现呢,对咱们数据库来讲,肯定只就咱们OM技术该该怎么选择,现在OM技术有很多啊,每个人都有不同的选择,呃,但在这儿呢,我在这儿优先推荐大家使用这个EF call,那当然对应咱们的这个啊,当然framework的话就是E,那么。呃,不是说其他的OM框架不能实现D滴D中充血模型能力相关的概念可以实现,但是至少经过我的这个粗略的研究啊,仅供大家参考。粗略的研究我发现这个EF靠是对于DD的实现最简单的东西,也就是说EF在设计之初就是为ddd而生的,当然我并不是说别的不是为DD而生的,只不过是我感觉EF实现ddd是最简单,当然啊,也有其他类似于EF靠,但是可能有人说感觉EF靠复杂什么之类,也有些别的呢,也是在往ddd方向来进行这个倾斜,但我感觉EF靠是最适合于这个ddd的。那么当然有的朋友啊,这个对于DD里有很多的误解,说什么ddd的这个。
40:42
性能低这个是怎么说呢?只能说是不会用,用起来的话,它会用的话,它性能其实一点都不低,OK,而且很多地方你有很多性能优化的方法,就是说低的性能低这一点彻底先否定,只是因为你不会用,而且它的学习的门槛其实并不高,几个关键点点给他突破了,其实EF也像其他的这个呃,这个OM一样,用起来非常的简单,但是带来的好处就是后续去实现ddd的时候,你会比用其他的OM史的实现的时候更加的轻松,所以说它就属于有一点学习门槛,但是一旦越越过那个学习门槛的话,你去实现ddd的时候啊,这个顺风顺水,而别的OM呢,可能上手时候比较简单一点,但是后续你再去实现D滴概念的时候呢,经常会遇到非常多的这个坎,那这是给家的一个建议啊,并不是说DVD必用EF call,但是推荐大家用EF call,仅供参考啊。那么关于这个事件,咱们说过了,这个事件有领域事件和这个集成事件。
41:42
那么领域实践值就是我一个进程内部的一个东西,那么这个的话,咱们一般现在用的比较多的就是这个mediator。这是一个进程。内部。呼叫微服务内部的一个事件分发的一个机制,而这个集成事件呢,有很多的这种MQ,因为集成事件就是跨微服务了是吧,呃,我这个微服务和这个微服我们来进行进行这个通讯。
42:06
啊,并不是直接通讯是。我把事件扔出去,我这个微服务呢,在收到这个事现,所以说最常用的咱们就用这个各种各样的MQ来实现,所谓的俗称就叫做event bus是吧,Bus。叫做中文叫什么事件,事件总线是吧,事件总线。OK,说说俗一点,其实就是这个MQ。MQ,我这网络信号怎么不好,IQ好吧?呃,那么MQ有很多什么rabbit MQ。什么XQMQ,什么各种LMQ都行,所以说随便选一个就行,但是我感觉do net里边用起来比较爽的MQ就是这个rabbit MQ OK,所以推荐大家使用这个,当然你用别的也行,那么关于集成事件呢,这块其实扩展开来啊,并不是说。它是等价的关系,就是关于集成事件这块啊。相关的概念,就是咱们的这个叫做最终业务的最终一致性。
43:05
数据的。最终一致性。因为在微服务系统里边很难有这种实时一致性,或者叫做强一致性,呃,像咱们数据库里边那种传统数据库里边这种事物在微服务中很难实现,咱们通常都要采用这种数据最终一识性来这个体现,而这个集成事件就是数,这个叫做这个数据最终一致性其中的一个重要的一环,那么现在有很多人关于最终一致性的一个框架实现,那么很多朋友学到这块的时候也是一个迷惑,就是说。一开始总是把这个数据最终一致性能一直认为说啊,会有一个类似于数据库里边这个事物这样一个东西是吧,选塞这样一个类拿过来,你要在咱们这个数据库里边,咱们这个传统DB里边这个事物是不是很简单,特别简单的一个begin transaction,呱呱一堆代码扔进去,最后一个roll,或者一个这个commit。然后要么全部成功,要么全部失败,特别的傻瓜化,但在微服务领域,要想实现这样一个最终一件一致性啊,没有一个现成的技术可以给你搞这个东西。因为最终一致性是无法。
44:13
通过某一个技术。单纯的进行实现的,你需要进行业务流程的规划。甚至里边要引出引入最终的这个人的这个手工的,这个手工的改错都有可能,那你这即使包括这个京东,淘宝这样的公司,很多的最终一致性,在有的场景下也得需要客服的介入才最终保证数据的一致性,所以说这个最终一致性它并不是一个纯技术问题,它是一个业务流程问题,所以这也是大家学习最终这个一致性的时候,可能一个一个迷糊的地方,在这儿给大家说,别找了,没有一个技术能够帮你实现最终一致性,这那些最终一致性只是帮助你来实现最终一致性,你还要做很多这种业务流程规划等很多这样的一些一些一些其他的事情,比如说这个微服失败了,你怎么样的重发一次事件,或者再怎么样的,呃,甚至通知一下管理员进行人工处理,什么都有这种可能,当然一些比较好的技术,你能让尽可能少的人工介入,但是不可能完全避免人工介入啊。这就是最。
45:16
最极端的情况就是一定有可能有人工介入的可能性,所以说这不是一个纯技术问题,所以说不要去想着这个找一个技术能够完全解决的问题,这是一个需要去大家需要注意的问题啊,那么当然啊,整个唯一服务需要。讲的东西非常多,我在这儿只有一个小时间给他去讲,没法去展开,我呢录了一套免费的视频教程,也不收钱啊,不要加客服小姐姐什么之类都不需要,大家直接到浏览器到视频网站一搜,他都能打开,好吧,呃,也是,也不需要花钱,什么都需要,所以在这儿呢,就是属于一个给大家告诉我录了一套这个免费视频,大家可以去看去,那么无论是在这个哔哩哔哩。呃,这个今日头条西瓜视频,甚至包括这个油管,呃等这平台上大家可以搜索到啊,那在哔哩哔哩B站大家就搜杨中科这个加V的就是我啊,你在我的首页就可以看到这条视频教程,全部都免费的,D相关的概念就是在这个160。
46:16
五节到184节,OK,后续还有项目啊,但讲滴滴的基础概念是在这儿,后续项目也都是免费的,全部都免费,都在这里边,全都有自取就行了,不需要加我微信,不需要找客服小姐姐,好吧,不需要找主角,啥都不自己去拿去就可以了,好吧,那么在这个西瓜视频,今日头条,你就搜这个,呃,程序员杨中科,B站的话就是杨中科啊,如果有朋友能像油管什么的话,也是杨中科就能找到了,好吧。行,呃,那这就告诉大家,我整个的详细的讲,比如说滴滴的一些这个概念是怎么回事,具体充血模型,这个拼血模型怎么去实现,然后具体实体类这个这个概念在EF中怎么用啊,包括说这个事件是怎么实现的啊,咱们怎么样的来进行这个领域事件,进行及时事件的这样的一个开发这个代码啊,我这都有,最后在在下边还会有项目的实战,好吧,那行,谢谢大家,呃,我讲了就到就到这的家,这就到这儿啊,大家有什么问题可以问一下。
47:16
好的,杨老师,我共享一下我的屏幕。OK。嗯,我取消一下共享啊。怎么取消?啊。我这暂停共享能啊结束共享看到啊好了可以了吗。好,非常感谢杨老师非常声情并茂的讲了这个ddd的内容,然后呢,我们是在B站、CSDN,还有视频号多个平台进行同步直播,然后朋友们都问了好多的问题,所以我就选了两个问题来让杨老师现场回答一下。第一个问题是充血模式中的方法和do service中的方法有什么区别?
48:15
呃,不一样,因为充血模型中的,因为充血模型它针对它是实体。包括这个实体下边的这个呃,这个聚合里边的其他实体,所以说它是一种小范围的业务逻辑,而像这个,像这个什么service呀,像这个domain呢,那里面的东西是更大范围的一个业务逻辑,所以说业务逻辑的这个范围,我这个这个这个这个这个实体中的那些方法,只操作我这个实体的那些呃字段,OK。好,杨老师第二个问题,记录日志a op更好还是ddd事件?这不是一个层面的东西,A op是一个具体的实现技术这个事件,它是属于一个,呃,这个是一个宏观的一个概念啊,就是。
49:01
这个事这个呃,这个这个事件可以用a op来实现,呃,那么具体具体做的时候啊,这个事件我是建议大家。我是建议还是直接写到这个代码里边,直接你把这个事件扔给你的事件组件就可以了,因为一般的事件组件啊,好的事件组件他都提供了这种异步的机制,所以说你把数据给他并不会导致这个性能有影响。并不会导致有性,因为在咱们系统里边日志记录还是比较频繁的一件事情,如果说你以这个事件往外抛的话,就会导致这个事件的这个中枢拥堵,那你要直接往这个MQ里边扔,那拥堵更严重,因为咱们系统里边很多地方都用到这个MQ了,那即使是你往这个呃,这个这个呃,这叫什么领域事件,或者往这个mediator里边扔,也会导致这个mediator特别的忙,因为事件非常多,所以说不如说直接扔给日志组件,让他去记,他本身再有一个异步机制,所以所以说扔给他,他慢慢再去往这个持久化里边再去记,不会影响咱们程序的性能。
50:06
OK,这是我的一个建议。好老师,最后一个问题。嗯。滴滴是推荐充血模型吗?不推荐使用仓储吗?这又是不同概念,呃,这还是两个层面东西,这个仓储是是那个层面的,然后充血模型是这个,我这个实体类该怎么设计的。这个我对实体这个类的一个修改,最终是由仓储来缓保存到我的磁盘中的,所以说我实体模型修改的是我这个充血,无论充血模型还是这个贫血模型修改的是我内存中的状态。它并不是我修改了name之后,立即数据库里边的name这个字段就改了,我只改了我内存中的状态,需要通过这个这个仓储来把它保存到数据库中,所以这个不不是一个层面的东西。
51:02
所以这其实就是很多朋友学滴滴的时候,很多概念最容易混淆的地方就在于概念太多了,有时候好像把完全不相关的两个概念进行比较了,这是我的一个看法。好的,谢谢杨老师,那我们的在线答疑呢就到这里,如果大家还有什么问题呢,可以扫描二维码进入到我们的直播社群,一会呢我们会拉杨老师进群里面为大家进行一个答疑,好,杨老师呢,会在21号晚上七点半到八点半还有一场直播,大家可以预约一下视频号的那个直播,预约那个通道,或者大家可以记录下来,然后呢,我们下个周的直播预告是另外一个老师的,是在4月14日周四晚上七点半到八点半,是由徐磊老师来讲,关于构建你的点NE6云原生开发环境,如果大家对我们的大赛呢,有什么不了解的地方,可以同时扫描屏幕中这个二维码进行一个咨询了解,那么我们今天的所有的内容呢,就到此结束了,大家可以到。
52:15
社群当中去把,你在看了杨老师的课程内容,有不了解的可以在社群当中去提问,杨老师一会儿就会花五到十分钟的时间给大家进行一个讲解,好今天的内容呢,就到此结束,大家拜拜。嗯,拜拜。谢谢杨老师,拜拜,嗯,拜拜。
我来说两句