第8&9周
2020年03月03日 - 2020年03月15日

编辑|子鱼

#问答与讨论

1.领域模型的版本,你们怎么管理?会落到文档中吗?还是直接用代码的版本,代替模型的版本管理?

[Zpl]

DDD少林派

➤ 问题解答
林杰16:59领域模型图,你是用什么表现的~
Zpl16:59目前……我是用代码demo
Zpl16:59没图
Zpl16:59有什么好建议
林杰17:01手画草稿图,然后用类图代替了.
Zpl17:06如果模型改变,也要同时更新类图?
林杰17:06我是这样打算的,但还没这样做
Zpl17:08有没有比较便捷的方式,用markdown的语法就能画出来
林杰17:08限界上下文图,领域模型图,领域行为图,领域行为流程图,但目前没有软件可以管理。只能手画,表达下大概的意思
林杰17:09http://plantuml.com/zh/
Zpl17:09嗯,这个我看到了
@nichole17:10想问一下,有没有哪个Markdown编辑器,可以支持嵌入PlantUML图的?
lincoln17:10我感觉可以搞个draw.io。这个有chrome离线版本的。而且保存到磁盘是个xml
子鱼17:13@@nichole语雀支持PlantUML
lincoln17:17plantUML我记得intellijidea也有插件吧。
lincoln17:18“林杰:限界上下文图,领域模型图,领域行为图,领域行为流程图,但目前没有软件可以管理。只能手画,表达下大概的意思”———————-要表达清楚这个plantUML的表达能力估计不够
冯炜19:03**问下大佬们。ericevans说:领域驱动设计只有应用在大型项目上才能产生最大的收益,而这也确实需要高超的技巧。不是所有的项目都是大型项目;也不是所有的项目团队都能掌握这些技巧

2.只有大型项目才能用这个?如果一般的项目难道不能用领域模型固化领域分析成果?那谈何有些公司只能垂直业务相关的软件。又谈何软件的核心竞争力保障,如何评估大型?这个不好界定吧。

[冯炜]

DDD少林派

➤ 问题解答
刘杰19:08小项目mvc没问题的~
小明同学19:13主要还是看业务复杂性,至于怎样算复杂还是得看实际情况和经验了
刘杰19:13可以看需要团队的规模
阿斌哥19:22在我看来只有纯粹的增删改查项目不需要DDD,其他的只要涉及到业务规则的,都可用。唯一需要考虑的是接手你这个项目的人懂不懂DDD
林杰19:22我记得书里有提过,大意是:在战略阶段,所有项目都可以使用领域(子域)划分和限界上下文。划分出之后,每个限界上下文采用什么方式设计和开发,视团队能力决定。
阿斌哥19:24我前段时间做的一个需求,分析下来就一个Entity,也用的DDD[表情],代码结构非常清晰,逻辑非常严谨,看的非常舒服[呲牙]
阿斌哥19:27虽说只有一个Entity,但还是涉及到上游系统,下游系统,任务调度系统,有RPC适配器,HTTP适配器,防腐层,领域服务,工厂,repository。一应俱全。就是聚合少了点,一个Entity,就这一个聚合[呲牙]
冯炜19:41谢谢大家点指点。我觉得只能说大项目看你怎么看如果只是看规模那就真的不好界定了。如果是看结构其实稍微大一点的就应该算是大项目了。看变化的话。如果需求容易根据业务动态调整的,或随着优化不断改进频度快的。我觉得都应该用领域分析建模

3.最近做了个openapi接口,有什么架构优化思路吗?数据请求进来我现在直接进行的逻辑判断,保存mysql数据库。数据量大了,cpu内存带宽都爆了,请高人指点迷津

_private_var_mobile_Containers_Data_Application_9D050B34-E08B-4B3C-A861-7710E56CD2F2_tmp_mail_wxid_reh9jd36w0p321_1621_thumb.jpg_private_var_mobile_Containers_Data_Application_9D050B34-E08B-4B3C-A861-7710E56CD2F2_tmp_mail_wxid_reh9jd36w0p321_1622_thumb.jpg
[张迪]

DDD少林派

➤ 问题解答
INCerry14:51@张迪有很多业务逻辑么?for循环数据拆解这些?
INCerry14:53如果有计算密集的东西的话那就要优化代码了如果只是IO密集CPU的话那就使用支持异步MysqlSDK会好很多内存的话我看也不是很高可以忽略
INCerry14:55java的话可以看看Vert.xJDBC客户端异步调用C#的话C#5.0就支持await/async了
张迪14:55异步还是会消耗cpu呀
INCerry14:56IO异步和普通异步是不同的概念
张迪14:57好的,我试试await/async优化下
INCerry14:58「张迪:好的,我试试await/async优化下」———————-C#还是python的项目?
张迪14:58c#的
张迪14:58.netcore
INCerry14:59C#记得awaitasync要从最底层的开始修改而不是直接Task.Run了
张迪14:59好的
INCerry14:59mysql驱动里面有conn.OpenAsync()conn.ExecuteQueryAsync()这样一些接口
方豪15:00方豪15:00@张迪今天看到的文章,guid有序化,可以提升性能
_private_var_mobile_Containers_Data_Application_9D050B34-E08B-4B3C-A861-7710E56CD2F2_tmp_mail_zydl19870811_1639_thumb.jpg
张迪15:00@INCerry全部加上async吗?
张迪15:00INCerry15:01你用的是entityframwork么?
张迪15:01@方豪文章链接发来我看看[微笑]
方豪15:01@张迪如果是.netasync里面嵌套同步操作,性能会极大损失
方豪15:02原文地址:https://mp.weixin.qq.com/s/-eeIXF7NUtkgELrFKbHVtA
方豪15:03@张迪之前用abp框架,经常爆卡,然后,前阵子官方说他们的设计有问题,就是async嵌套设计的问题
张迪15:04@方豪我之前使用的是abp,后来放弃了
张迪15:04不适合高并发,可能是我不会用
方豪15:05@张迪官方也承认不适合高并发,要自己改进
INCerry15:07大批量的数据删除读取插入建议使用DapperEF更适合做领域内的对单个领域实体的操作
INCerry15:09**EF和Dapper完全可以混用的官方也有EFCore的Dapper扩展

**4.请教一下各位大佬,有没有值得学习的实践了DDD的开源项目可以介绍一下?

[小明同学]

DDD少林派

➤ 问题解答
远远鱼21:05**https://github.com/ardalis/CleanArchitecture我还没看,不过看star有4k

4.大家在DDD实战过程中会编写用户故事吗?在什么阶段编写呢

[深山小书童]

DDD少林派

➤ 问题解答
阿斌哥11:49这个是属于分析阶段要做的事情,用户故事只是一种帮助我们了解业务的方法,还可以通过事件风暴来探索业务全景。这些都属于需求分析阶段,可能还有其他的方法,每种方法肯定也都有优缺点和适用场景,也可以自创需求分析的方法。这跟技术选型是一样的。
Zpl11:53像一些计数类的属性,你们会设计为领域对象的属性吗?
Zpl12:09具体的场景是,比如一个帖子,有多少回复
lincoln14:09给运营用的后台管理端的业务模型,大家会单独建模和部署么?还是和提供给C端的服务整体建模,部署在一块?单独建模部署:缺点:有些逻辑会分布的2个地方,不够内聚优点:运营端和C端需求量不同,发版频率也不同,互相发布不影响整体建模部署:优缺:逻辑统一,够内聚缺点:需求量不同,发版频率不一样,这个发布有可能影响另外一个
远远鱼14:12如果是核心域,且业务足够复杂,推荐单独建模。这是典型的“限界上下文”里说的多个(目的不同的)模型
远远鱼14:15我有点好奇你说的“有些逻辑会分布的2个地方”是哪些逻辑?还是只有数据是同样的?
lincoln14:17比如,修改数据的把订单延期支付
远远鱼14:24那和我想的不一样。刚才我想的是比如产品,运营配置,C端查看,所以可以是两个模型。订单之前我的思考都是,拆成用户订单、支付单、配送单等,没想过可以按运营和C端拆
lincoln14:26就是:C端用户对订单的操作,和运营人员对订单的操作是不同的?运营人员,一会提个这个需求,一会提个那个需求。这些运营人员提的需求是不是可以独立建模型,独立部署?
远远鱼14:30提的需求可以举个例子么?
lincoln14:36比如:各种查询,有点类似报表的功能。那是不是:更新类的操作就最好内聚在一块,查询类的可以单独建模?还是说有一些方法论可以区分我感觉你刚才说的根据目的不同分别建模有点说服力(分开建模)
远远鱼15:03查询的确是不同的目的,对修改和查询分开建模,这种情况比较常见,已经有成熟的模式叫CQRS
远远鱼15:04如果两边都修改同样的数据,
lockness15:08查询是不要建模的
远远鱼15:09比如你刚才说的,运营“修改数据的把订单延期支付”,C端会创建订单。这种情况我之前没想过。也许分开建模是个可行的方案或者,也许两个模型可以合成一个,如果没有冲突,而分开看上去又没太多好处,我觉得合成一个也不错。
远远鱼15:14“lockness:查询是不要建模的”———————-同意~
lincoln15:17**嗯,其实主要还是修改。查询怎么都好说。CQRS分开,可以防止领域层逻辑被查询腐化。

5.想问下大家这张图里限界上下文A里的两个聚合在本地事务里可以做到强一致,但是原则上一个事务只修改一个聚合实例,这里是做的妥协吗

[lilpilot]

DDD少林派

➤ 问题解答
darvin00:11我对此也有疑惑,好像是用工作单元模式是用来解决跨聚合的事务
石建09:49我认为:原则上一个事务只修改一个聚合实例,是对DDD过于。1、聚合:是在强调需要在业务上保持一致性的约束,如:常见举例,删除帖子,必须删除帖子下的留言。2、常见:帖子、留言,在不同业务场景时,其“一致性”约束并不相同,如假设:修改留言,并不需要判断帖子的信息。因此大家会把帖子、留言,作为两个独立的聚合。3、但删除帖子的场景,就需要保持“业务一致性”。我们会通过技术手段,如数据事务,来保证强一致性,此时就是会在一个事务里,修改两个聚合实例。
石建09:49我认为:原则上一个事务只修改一个聚合实例,是对DDD理解过于教条。
右军09:53反过来看聚合的粒度
李剑虹10:56应该是一个限界上下文中只修改一个聚合吧,
李剑虹10:59一个事务可能会设计到多个限界上下文的数据变动,但在同一个限界上下文应该只有一个聚合需要变动,在该聚合内保证事务一致性,不同限界上下文保证最终数据一致性。
lockness11:03严格来讲,一个事务就只改一个聚合跟。为什么会改多个聚合,可能理由是减少复杂度,其实如果多个上下文你实现最终一致性,为什么不在聚合跟之间实现最终一致性,
刘杰11:04我们是在实现中,是可以一个事务更新多个聚合根的。服务内最终一致性增加了工程落地的复杂度。
lockness11:04多个上下文不也是多个聚合跟基础设施比如saga都有了就别懒了吧
lockness11:04妥协就是复杂度的问题
lockness11:05多个上下文那你也是在一个事务里?
刘杰11:06event是push的方式,事务是pull的方式。我们是按照微服务,微服务内就用事务(微服务按照上下文去划分),在服务内用pull的方式是可控的。
lockness11:25可以看下enode汤雪华大佬的一个架构图

6.请问大家2个问题:1)实现聚合根的写操作时,要不要给聚合根传入一个Repository的接口?a.传入的方式。但查了一些资料都是这样会导致聚合根不够纯粹,耦合了持久化的逻辑b.不传入。由应用服务先调合聚合根的写操作,再吊用repository做持久化。但这样的问题是,应用服务和repository不知道聚合根里面修改了什么(除非做changetrack),只能整个聚合根做覆盖写吗?如果做changetrack,在分布式环境下很难保证多副本的一致性2)领域服务实现时,能否给领域服务传入一个repositorya。传入。有观点认为,领域服务不应该依赖repository,道理和聚合根场景一样b。不传入。领域服务典型的是要协调多个聚合根完成逻辑。多个聚合根可能分布在不同的微服务和部署节点。如果不能直接调用持久化,逻辑实现起来很复杂。


[darvin]

DDD少林派

➤ 问题解答
小浩子12:06领域服务持有repository(的抽象),分布在不同微服务的由各自微服务负责持久化
远远鱼12:30聚合不应该依赖于资源库。聚合等领域模型是表达“领域概念”,会被加入通用语言,用来和业务沟通用的。而业务不关心资源库这种虽然在领域层但是承担偏“技术”的东西。
远远鱼12:31聚合也不需要承担自己的持久化的职责。它本身的职责就够多了
darvin14:20@远远鱼是的,网上查了一些资料也是这个说法。不过我在网上都没有查到我上面列的一些实现难点是如何解决的
远远鱼14:43>但这样的问题是,应用服务和repository不知道聚合根里面修改了什么(除非做changetrack),只能整个聚合根做覆盖写吗?对,就是这个覆盖。聚合就是要保证内部状态一致。这里会引出并发冲突的问题,可以通过各种锁解决。这也是聚合要尽可能小的原因,大了冲突会变多。
darvin14:50举个例子:我们有一种常见的聚合,订单和订单项。如果写操作都要更新整个聚合(订单和所有订单项),看起来太重了
远远鱼15:10为什么说“太重了”啊?可否展开说下?数量多?字段多?
darvin15:20比如,只是其中一个订单项退货,那么就需要把所有订单项重新覆盖写一遍
远远鱼15:25订单和订单项是否一个聚合,除了1看他们的生命周期是否一样(一起创建,一起删除),还看2它们之间是否有固定规则,比如一个订单的订单项数量不能超过3个,还看3并发冲突,是不是有很多人在同时更改一个订单是否所有都要覆盖,并不重要,这是个技术问题,可以通过使用合适的框架和数据库减少复杂度,而不需要影响领域模型
darvin15:27订单和订单项生命周期是一样的。但可能会有部份退货/退款情况。脱离一个订单的订单项是没有意义的
远远鱼15:29>脱离一个订单的订单项是没有意义的是的。不过不是一个聚合并不意味着他们之间没有了关系。聚合之间也可以有关联。
远远鱼15:30刚才说的3个点,是同时都要考量
darvin16:56@远远鱼请问领域服务可以依赖于repository吗?
远远鱼17:07“darvin:@远远鱼请问领域服务可以依赖于repository吗?”———————-这个问题我还没想清楚现在我的初步想法是,可以依赖。包括值对象也可以依赖。值对象也分为需要持久化的和不持久化的,不持久化的可以依赖repository。但关键问题不是是否可以依赖,关键问题是领域服务和值对象要能表达领域概念。在表达领域概念的基础上,需要用repository的话,就可以依赖它。
陈瑞17:23领域服务一般都会依赖repository,但不要直接依赖,要做倒置
darvin17:25嗯,倒置时基础的要求
Zpl17:28领域服务依赖repository,应该是动态的聚合对象的时候,才会需要;
Zpl17:28就是调领域服务时候,不能确定参与的聚合;
Zpl17:28才会需要调用仓储
aaa217:29没领域服务的聚合在哪里调用仓储?
Zpl17:31app
aaa2
17:32Enode中是产生领域事件这个在应用层调用吗?
Zpl17:33没仔细研究过;enode
Zpl17:33你应该在enode群问
aaa217:33只是看过Enode源码,如果不用es的情况下如何做
Zpl17:33CQRS/ESenode的架构好像是这种
sunjun18:12在针对质量属性进行软件架构时,领域驱动设计就力有未逮了
sunjun18:13质量属性怎么理解
阿斌哥18:14可以理解为非功能性需求
小浩子18:26*
技术指标和客观约束

7.我们在实践ddd,发现按照事件风暴,系统变成了只有一个聚合,这样代码还是混在一起。怎么把聚合拆细?求指点,谢谢大家

[覃逢春]

DDD少林派

➤ 问题解答
忘却录音23:22根据用例去分析
忘却录音23:22然后画出用例活动图,
忘却录音23:22然后根据功能相似性去划分
覃逢春23:25我们的生产单,创建,下传生产系统生产,过程中想取消,在下传一个取消
覃逢春23:26把两个下传聚合在一起
覃逢春23:26感觉很怪
阿亮23:26在业务场景中,实体或值对象的状态需要满足业务规则的一致性,可以划分成一个聚合
覃逢春23:27针对生产单还有很多操作,没有列出来
覃逢春23:29从理论上,这些都是围绕生产单的行为,如果放在一起,担心代码结构又回到从前,成了一锅
右军23:31「覃逢春:我们的生产单,创建,下传生产系统生产,过程中想取消,在下传一个取消」———————-可以把用例画一下分享出来,围绕生产单可能也是一个潜意识
覃逢春23:34老系统重构,有很深的固化思维
阿斌哥23:37没看懂什么叫“把两个下传聚合在一起”
阿斌哥23:38仓储系统吗?@覃逢春
覃逢春23:40仓储的上游,内部生产单据管理
覃逢春23:43下传到生产系统生产,有原因要取消,取消前要先跟生产系统握手,确认还没开始生产才能取消,这个握手是通过下传(掉接口),回传(监听mq))来做的
覃逢春23:44就有两次下传,有部分同学把这两单独放一起,从生产单中分出来
右军23:44偏工作流,看起来
阿斌哥23:51**下传是一个技术词汇,业务上来说应该叫做:创建生产单和取消生产单。这是两件事情啊,为啥会有“两次下传”这种统一语言。没看太明白你的问题所在[呲牙]

8.问下你们调用repository持久化是在聚合里面做的吗

[刘杰]

DDD少林派

➤ 问题解答
远远鱼10:11不是
lincoln10:42首先我的回答没啥权威性,才了解DDD不到一个月,而且都是略看,没有细读。我从看过的资料说下主要借鉴了三个:1、gitbook.cn张老师的课程2、极客时间欧创新的DDD实战课程3、githubCOLA框架前两个都是在聚合的领域服务里面调用repository,最后一个没有领域服务这层,只有应用服务这层,在这层里面调用了repository
_private_var_mobile_Containers_Data_Application_9D050B34-E08B-4B3C-A861-7710E56CD2F2_tmp_mail_hackerster_1792_thumb.jpg
lincoln10:44如下图所示,COLA的就没有贴出来了:
lincoln10:44lockness10:54讨论resposity和事务远多余讨论怎么统一语言怎样划分上下文和设计聚合跟
lockness10:56不用DDD一样要落库吧极端点直接用SQL语句落库也行呀
小明同学10:59没必要过于教条,做到依赖倒置,我觉得对于repository接口的调用放在领域或者应用服务都行
小明同学11:00保持风格统一就行了,别一会领域里面调一下,一会应用服务里面调一下
远远鱼11:02“DDD是啥:要是英文版能看懂,谁看中文的[捂脸]就是吃亏在英文了。”———————-http://gdut_yy.gitee.io/doc-ddd/有人做了Eric的蓝皮书的中英文对照版,特别棒
远远鱼11:08“lockness:讨论resposity和事务远多余讨论怎么统一语言怎样划分上下文和设计聚合跟”———————-我之前也是更关注架构、事务这些,这些问题大致解决后,我发现我的“领域模型”能力还是不足,现在注意力转向了领域模型以及基于模型的通用语言、柔性设计这些
lincoln11:17其实,我刚接触(现在接触的也不多)开始DDD,尤其是充血模型,就有个疑问:那是不是保存也是聚合根或实体干的事情,也就是实体也得引用repository,因为程序员首先想到的就是代码。虽然DDD最重要的是战略设计(统一语言)这一部分。后来看了一些文章,真有这么干的:盒马的张群辉写的一个InfoQ上的:阿里盒马领域驱动设计实践.就是实体里面引用repository。后来又参考了3个不同人(极客时间、gitbook、阿里张建飞的COLA)代码结构:大部分还是领域服务、应用服务引用repository。
刘杰11:21国外的一般是在实体里面引用repository,因为repository是依赖倒置的,关系也不大。我现在认为是贫血和充血的区别
lincoln11:25@远远鱼我其实还是在吸收阶段,没有自己的见解,只是参考。这经历了20来年也没确定的了的问题…..估计不好确定。
远远鱼11:26推荐两个repo,分别是Eric蓝皮书的代码和IDDD红皮书的代码:https://github.com/citerus/dddsample-corehttps://github.com/VaughnVernon/IDDD_Samples

9.有没有什么ddd比较好的项目

[忘却录音]

DDD少林派

➤ 问题解答
方豪11:46@忘却录音微软eshopOnContainer
方豪11:46@DDD是啥请问有没有电子书?
方豪11:46@忘却录音abpvnext微服务项目
huiter11:59看到之前群里有讨论订单域要不要按照C端和运营进行拆分,我理解运营域可以通过订单域完成“写”类的操作,常规“读”类操作可以通过订单域,针对运营场景定制化的需求也可以运营域读取订单数据来实现。订单域作为底层模块,提供的能力应该不受业务域特殊需求的影响。

10.我看在COLA里面,controller的入参可以直接是cmd,你们在实践中也会这么做吗

[刘杰]

DDD少林派

➤ 问题解答
阿斌哥16:02会的,这么做没毛病
刘杰16:03那在一个command最终落库只要经过三个转换是否就够了cmd->domain->PO?
阿斌哥16:11controller是适配器,目的是将HTTP协议最终转成应用服务能识别的协议,即xxCmd。放到controller的入参那里,只不过是依赖SpringMVC框架,一步转换到位了而已。非要定义一个xxRequest,再在controller里面把这个xxRequest转成xxCmd,也是可以的,只是没必要。我是这么理解的
刘杰16:13我们现在是转换,发现这个转换的确貌似意义不大
阿斌哥16:13不经过PO也可以啊,domain直接持久化也是可以的。中间是否要经过一层,之前讨论过几次了。各有优劣,自己权衡吧。我是感觉很多东西没有唯一正确的标准。
刘杰16:14PO加一层我感觉还是有必要的,domain作为最内层,不依赖任何其他东西
INCerry16:16Repository可以依赖domain直接映射Entity持久化吧
阿斌哥18:04阿斌哥18:04**这个地方我有一点疑问:如果共用了消息契约的话,这个消息契约是上游限界上下文的,这里的to方法的返回值是下游上下文里面的领域对象。这样一来上游限界上下文就依赖了下游限界上下文的领域对象。这种依赖不知道大家怎么看?

11.请问领域服务的入参你们都是平铺还是会构建个参数的实例啊

[刘杰]

DDD少林派

➤ 问题解答
炙炙炙炙炙炙云深17:50app层到domain层?先构造实体(值对象、聚合),再传入
炙炙炙炙炙炙云深18:02我们用了[表情]
秋沢凡18:04**刚才有一个feign的接口类少了几个api我又不能改源码这种情况是不是得重写一个feign了

12.各位,对于领域事件的订阅,具体订阅后的处理你们是直接放在handler中处理还是由handler转移到领域服务中处理哟

[因即果,果求因。]

DDD倚天剑

➤ 问题解答
鹏酱[表情][表情]12:44通过应用服务
因即果,果求因。13:32不会吧,通过应用服务?[表情],我目前是转移给领域服务去处理

13.各位老师,大家好,想从字面上细扣下“Context”和“BoundedContext”,为啥叫Bounded?

[王喜春]

DDD倚天剑

➤ 问题解答
JAMES🦁17:09有界的
王喜春17:10嗯,直接翻译过来是有界的。
王喜春17:10再往下看看,为什么要有界?
王喜春17:11无界的Context有什么缺点?
鹏酱[表情][表情]17:11就因为有缺点所以才有DDD
王喜春17:14也就是说,没有DDD前,整个公司虽然有一个Context,但范围太大,对应的系统也是单体,系统的维护成本太大,沟通成本太大。就分而治之地对Context拆分,这些被拆分的Context就是BoundedContext,对吧?
lyning17:46就算你没听过ddd,你也可能会根据需求对系统进行拆分
゛没有名字づ18:10**名词定义而已,在DDD里,BoundedContext指的是对业务领域进行分析划界后形成的领域上下文

王喜春08:07[终于闹明白了啥叫限界上下文,解释接地气,不花哨:]
王喜春08:08昨晚文章的一个翻译,希望对大家从另一种角度理解界限上下文有帮助
王喜春08:09也请大家多指教。
王喜春08:34上面红框里话的内容是说:事件风暴过程中,使用便利贴写下事件/命令/角色后,再把这些意识和概念下沉,使用代码定义出这样概念。理解是不是到位?
王喜春08:34原文地址:https://medium.com/ingeniouslysimple/constructing-your-ubiquitous-language-7a57e36e3e82

14.想请教一下大家,我们在写一段逻辑或者需求的时候,有没有一些理论或者业界大家共识的标准,去区分是业务逻辑还是领域逻辑呢?

[王喜春]

DDD倚天剑

➤ 问题解答
鲍俊伟09:40「小Z:想请教一下大家,我们在写一段逻辑或者需求的时候,有没有一些理论或者业界大家共识的标准,去区分是业务逻辑还是领域逻辑呢?」———————-业务逻辑不就是领域逻辑吗?
beforeturning09:43我理解是:业务逻辑(产品逻辑)有些容易变动的,想放到业务逻辑成,公用的逻辑,复用性很强的,我理解为领域逻辑
beforeturning09:44一个需求过来了,要写一段逻辑,只能见仁见智的去拆这段逻辑,判断哪些部分是公用的,哪些不是公用的吗?
beforeturning09:44成—-层
鲍俊伟09:46那应该可以理解为:业务逻辑=流程逻辑+领域逻辑,前者灵活多变,后者稳定复用
beforeturning09:46想表述的是这样,就是有没有大家共识的标准去拆分一下这是容易变动的逻辑,哪些是不容变动的。
beforeturning09:47可以这么说
鲍俊伟09:50那只能是结合业务特点和业务发展作出判断,但所面临的问题域,通常业界会有一些常见的案例,如电商领域等。对行业和业务理解深刻的话,就可以容易区分不同逻辑
鲍俊伟09:51可以参考阿里的tmf,你说的业务逻辑VS领域逻辑的区分,可能会得到些收获
beforeturning09:53领域逻辑里面也会包含一些流程的体现吧,领域的流程逻辑和产品提的一些产品逻辑,这块有比较好的区分吗、
因即果,果求因。09:55「鲍俊伟:业务逻辑不就是领域逻辑吗?」———————-我所了解的好像不是一种,业务规则,业务逻辑,领域逻辑,我看到的是三种,且概念不一样
鲍俊伟09:56「因即果,果求因。:「鲍俊伟:业务逻辑不就是领域逻辑吗?」———————-我所了解的好像不是一种,业务规则,业务逻辑,领域逻辑,我看到的是三种,且概念不一样」———————-那可以给一下三者的定义吗?
beforeturning10:18「鲍俊伟:可以参考阿里的tmf,你说的业务逻辑VS领域逻辑的区分,可能会得到些收获」———————-@鲍俊伟这个你有好的文章推荐一下,感觉没有搜索到比较满意的[抱拳]
beforeturning10:18就是想寻找业界有没有共识的标准或者方法论,来进行逻辑区分
鲍俊伟11:28**首先,要明确给出这些“xx逻辑”的概念,才能再去讨论(不然大家的理解不一致,没法交流)

15.实施微服务后,现在有70多个业务服务,他们之间有时候相互调用,感觉比较混乱,整个体系耦合度反而高了,各位大佬,有什么好的建议和方法?有时候需要一个接口,就得调多个业务系统

[Anything]

DDD屠龙刀

➤ 问题解答
霍尔顿10:59微服务外部依赖很高的话首先是不是没划分好啊?
Anything10:59业务职责来看,系统的划分感觉没什么问题
霍尔顿10:59我们也有这个问题,,用的bff模式
反应慢10:59调用用来查询还是用来更新?
Anything11:00查询
霍尔顿11:00目前感觉最大的问题就是model爆炸,,各种重复的model
Anything11:00这样造成接口性能很差
反应慢11:00你可能需要一个中间的系统,做数据中心
霍尔顿11:01服务间调用用的什么
反应慢11:01这个系统去其他系统里搜集数据
霍尔顿11:01httprpc?
Anything11:02现在是两个都有
Anything11:02@反应慢我们做了类似的数据中心,异构系统来的,有延时性或者准确度方面的问题,现在还是很多直接调用业务实际系统
Anything11:03也有API聚合层,但是还是从业务系统拉接口整合,性能还是很差
反应慢11:03一致性问题,应该引入中间状态来解决吧
反应慢11:05上游把状态变成XXX_PENDDING,中间件更新之后,变成XXX,所有系统都去中间件查的话,一致性问题应该能解决
反应慢11:07如果应用一方面从原始系统查,另一方面又从中间件去查,数据不一致就是常态了。
Anything11:08很多业务实时性要求可能相对高一些,就从业务系统去查
Anything11:08性能方面真是一个堪忧
霍尔顿11:08我们一般控制下调用链长度,非关键的用mq异步处理,性能还行。架构复杂,性能损耗是肯定的,只能自己找平衡点
反应慢11:08我的理解哈,如果对实时性要求高,那么它就应该是数据的拥有者
霍尔顿11:10之前在书里看到的观点,微服务如果有外部依赖,其实就不算是微服务
霍尔顿11:10应该是自治独立的
小松11:10@反应慢这个引入中间状态好像是解决隔离性的问题的
小松11:12拆分的太细了。是不是可以考虑合并一些。。
小松11:13或者是通过中间聚合服务。。
X11:15这个问题是个好问题啊。。再多深入聊聊吧。。
霍尔顿11:16搞中台合久必分分久必合[呲牙]
Anything11:16聚合服务,看是怎么样的服务,如果类似网关,下面还是调用业务系统接口,性能问题还是无法解决
反应慢11:17还好吧……大厂基本上都会构建订单中心之类的服务解决这个问题
反应慢11:17负责订单生命周期管理,数据也比较全
Anything11:18供应链的服务,涉及采购,仓储,物流,履约,从订单下来,采购入库到调拨到各种业务(上牌等),最后到交付
反应慢11:19但是订单中心的代码看起来会比较恶心。一方面表会特别宽,另一方面逻辑特别琐碎
X11:20我们可以把问题聊得更具体一些。。从一个实际的例子聊聊。。查询的例子也好命令的例子也好
吴林峰11:20你们咋会拆到这么多70多个服务接口出来,叫你们拆分系统,不是说把系统拆分出来独立部署成微服务。
小松11:20流程这么长,可否采取基于消息队列提供服务通讯能力
X11:20是性能问题还是延迟问题还是调用链路问题。。
Anything11:21现在很复杂,有走消息的,有走业务接口的,有走聚合层的
反应慢11:2170多个服务还好吧
小松11:21调用链长了。。性能、可用性也会下降。
小松11:22看团队规模,以及服务治理能力吧。。
吴林峰11:22拆成逻辑边界的就行了,有性能问题需要横向扩展的才需要横向部署成物理边界的
Anything11:22感觉把业务的复杂度转换成技术的复杂度,表面业务系统的划分业务职责很明确,但是底层架构看,数据依赖还是挺严重的。
小松11:23数据依赖严重,那就得考虑是否要冗余数据了。
X11:23你的意思是服务间业务耦合严重吧
小松11:23就像@反应慢这位大佬说的。。
Anything11:24@小松冗余数据,就要考虑一致性问题
小松11:24我看他们是服务拆分太细。。然后很多冷数据没做好冗余。导致经常性的跨服务调用。
反应慢11:25某东的履约过程,从路由,分拣,运输,仓储,配送,售后,客服等等各色系统就不止七十个了,靠运单系统串起来
小松11:25有时候,真的没有太大必要担心一致性问题。
反应慢11:25下单过程还有订单中间件
X11:25可能不是冷数据我猜是A服务的业务进行需要一些B服务的业务逻辑作为前置或后置条件
小松11:25一致性问题,一部分是可以通过技术手段,一部分通过业务手段降低的
冯11:25世界本来就是不一致的,何必强求
X11:25如果做冗余要考虑数据同步。。不做冗余又要考虑调用复杂度
Anything11:25@反应慢我们的基础措施差,服务治理难度大
小松11:26@冯哈哈,有道理。
反应慢11:26不聚合数据就先聚合能力吧
郑承良11:26这个问题好。我把问题整理一下,是不是可以分开聊。问题1.微服务拆分70个,微服务之间耦合,调用混乱。问题2.微服务调用链长,担心性能问题。问题3.各种model很多,model膨胀。
冯11:27所谓的冗余,你怎么保证冗余的数据足够满足后续的需求
反应慢11:27我最近在看企业集成模式
反应慢11:27我觉得挺有意思的
小松11:27我们这边,一部分是通过消息队列保证数据一致性,一部分基于canal做数据同步。
Anything11:28@小松都有的
反应慢11:28没有一个中间件解偶,可能回出现循环依赖的问题
反应慢11:28那就不得了了
Anything11:28我们现在是异构宽表的形式,构造维度宽表,去打通各个业务系统的数据孤岛问题
Anything11:29@反应慢也有部分情况,哈哈
小松11:29也就是和上面说的,数据中心类似的做法一样。
冯11:30冗余只能治标,而且后患无穷
小松11:312,8定律吧。找出最影响业务的几条链路调用,看看他们有没有共同的做法。
小松11:32不要想着一个法子,一下能解决所有问题的。。[捂脸]
反应慢11:33做一个订单中心或者履约中心,各个系统的状态以这个中心的状态为准,业务系统更新状态之后,去这个中心更新才算真正的状态更新成功。
反应慢11:33然后这个中心驱动着外围业务流转。
反应慢11:34要有两套流程,一个是信息流,以这个中心为主。一个是实物流,以业务系统实操为主
反应慢11:34后面就变成两个流程的状态同步了
反应慢11:35业务系统的依赖,应该是依赖信息流
雪山11:35雪山11:35这个在哪里可以下载到
右军11:36「小成:实施微服务后,现在有70多个业务服务,他们之间有时候相互调用,感觉比较混乱,整个体系耦合度反而高了,各位大佬,有什么好的建议和方法?」———————-如果有双向调用,往往服务划分有问题。通过服务治理工具看调用链路图,梳理合理的调用;支付宝我记得3-5年前上千个应用,还不是上千个服务。但主链路在10-20个应用这样的规模,能异步的异步,比如账务到会计,能非实时的非实时,比如交易记录同步到用户侧的消费记录,还有一些在大促做降级或者部分降级,比如实时的一些逻辑,一直到这个局部容量提升到足够之后调整为不降级。
右军11:37由于支付工具比较多,不像微信。这一块多支付工具组合支付采用了TCC模式,其它场景基本使用的是异步可重试事务模式
wingyiu11:55saga也可以搞一搞
_CountingStars12:05我有一个关于敏捷和DDD融合的疑惑,DDD应该在敏捷的什么阶段进入比较合适,敏捷强调小团队干小事情,而DDD一般用于处理复杂的项目,DDD和敏捷应该怎么结合呢?
薄军12:09先DDD吧
反应慢12:10敏捷强调沟通高于工具,沟通的过程就是构建领域通用语言的过程,在沟通的过程中,或者在产品的迭代中,人们对于领域概念的理解也会不断发生更新,代表着领域通用语言的变迁
反应慢12:11DDD也没规定领域通用语言是一成不变的
反应慢12:11需求评审,迭代回顾,这些都是加深对领域概念理解的过程
汪汪12:15一个是对于软件工程的方法论一个更侧重与系统设计、建模
反应慢12:16在不断的交付过程中,大家也是根据领域概念的理解进行验收
反应慢12:18QA同学对RD同学的代码逻辑不认同,就是领域概念认识不统一造成的
王大宝12:22rd啥意思?
反应慢12:22**开发

16.请教各位海量数据(主要是各种设备的事件)用于统计分析一般考虑用什么数据库来存储?ES靠谱吗

[汪汪]

DDD屠龙刀

➤ 问题解答
任富飞19:49**靠谱,现在大家都支持HDFS

17.有crossingedge这样的提法不?我记得有个类似的单词,代表跨边界的通用服务或功能。比如安全,日志这样的东西。

[汪汪]

DDD屠龙刀

➤ 问题解答
反应慢10:01crosscuttingconcern
朱永光10:04哦。我把cutting记成edge了……

18.请教大家一个设计上的问题一个物联网项目,打算部署flink做各种设备的数据采集,计算,报警等,但实际上设备的种类从业务的角度是不同的应用层面也是划分为报警的,纯数据采集统计类的,那像这类的话flink是跨领域边界部署,处理所有领域的数据?还是各个领域内部署,只处理自己的

[汪汪]

DDD屠龙刀

➤ 问题解答
JAMES🦁09:07flink是写脚本放到上面运行的吗
JAMES🦁09:08应该是可以调API创建脚本?
JAMES🦁09:08我用过influxdb的
sunny09:10职责划分还是根据业务领域来分析,只是说你要不要将数据采集和报警的业务功能化到单独的业务领域,还是跟它关联的业务领域放一块,这个本身跟flink没有关系,flink只是一个流式计算框架。
汪汪09:18flink是调API
JAMES🦁09:19你把api封装起来,作为一个组件
JAMES🦁09:19适配器
JAMES🦁09:19你的业务调它
JAMES🦁09:20业务逻辑是领域内的
sunny12:14这个选择的放到那里的原则与业务拆分,微服务拆分的原则是一样。如果当前基于大数据的数据分析业务很小,数据的源头也比较单一只涉及到某个业务领域,简单起见就可以放到与它关联性比较大的业务领域内;如果基于大数据分析的业务需求比较多,场景比较复杂,可以预见未来的需求会越来越多,会涉及到多个业务领域数据的聚合场景。那么可以将基于大数据分析这部分独立开来,因为这部分技术,逻辑,模型类似。
汪汪12:15谢谢各位意见
汪汪12:16**结合业务考虑一下可能目前还是独立比较简单

19.有朋友在生产项目中用jetcache替换springdatacache作为缓存封装方案的吗?https://github.com/alibaba/jetcache

[sunny]

DDD屠龙刀

➤ 问题解答
反应慢13:19数据字典类的应用吧,其他更新比较频繁的不太合适
sunny13:21主要应对高并发的场景,提供了基于1、2级缓存的灵活配置方式内存缓存,redis分布式缓存。
反应慢13:22缓存一致性很难搞
反应慢13:23本来缓存和持久化之间的一致性就很难搞了,再加一级,更难
sunny13:23相比springdatacache解决了使用缓存中涉及到缓存预热,缓存穿透,缓存雪崩,缓存失效机制等问题。
sunny13:23是的,缓存一致性的问题需要继续在这个基础增强
反应慢13:24所以,这玩意就适合数据字典类型的
sunny13:25有些具体的场景,数据的实时性没有那么高也可以用啊。
sunny13:26缓存一致性的问题,目前应该没有什么好的开源方案吧。
反应慢13:26比如?
sunny13:28页面上数据变化频率不高,用户对正确性不那么敏感,在加上缓存可以周期刷新,这样的情况下也可以用。
sunny13:29jetcache这个东西主要是在你要使用springdatacache的时候,jetcache提供了一种相对springdatacahce更好的使用方式。
反应慢13:30缓存5秒,就有可能5秒钟不一致
sunny13:31所有得考虑用于一致性没那么高的场景下。
sunny17:24**其实在贫血模型中,某个业务单元划分出来的微服务,如果暴露给外部的接口都是以主要模型(对应根聚合),举例来说如订单微服务主要实体模型是Order,再加其他很多相关的实体,如果订单微服务给外部提供的实体模型接口都是都以OrderApi这样的类提供出去,那么贫血模型也可以具有充血模型的优点,并且也可以保留自己的优势。