最后更新于2023年3月10日 14:28:08
问题建模=》软件分层=》具体结构,是层层递进的关系。有了问题建模,才能进行具体的软件分层的讨论,再有了分层,才能讨论在domain里面应该怎么实现具体结构。
1、问题建模:Domain、Model、Domain Model
领域驱动设计中的领域模型是什么? 这里面说的挺对的,领域模型是处理问题的条理化和结构化的知识,而领域本身就是问题/就是需要解决的业务。对甲方的需求的分析(甲方公司的需求、业务、规则、流程等)组成了domain。
先有了领域模型这个东西,再将领域模型转化为具体的代码,而代码的转化就要分什么用户界面/展现层、应用层、领域层、基础设施层,再往下才是具体的设计,什么实体、值对象之类的。
2、限界上下文
看起来它是对前一小节完成的领域建模的一个划分。
3、软件分层:User Interface、Application、Domain、Infrastructure关注点分离,构造四个概念层
DDD 架構: 分層式架構與依賴反向原則 这个博主讲话真的有够机车的喔!他这个也是稍稍深了一点。
DDD架构的重心是围绕Domain层进行构建的
6. Domain-Driven Design - Layered Architecture 这个挺好的,比较浅。这哥们儿在infrastructure那写的很烂,看得出来是懒得写下去了。写麻了是吧 点开他的个人资料,有一系列文章,应该都不错。
这一层可能是指前端,但是在一些没有前端的程序中,客户指的是外部的其它系统,于是也可以理解为暴露给外部使用的一些API。
这一层还有传统意义上的controller层的功能,即将传入的request转化为应用程序层的方法调用。
“负责为每个服务调用启动事务”是什么勾巴意思?!这里应该跟事务脚本模式有关。
几个栗子先,下面这是一个Application层的函数,从上面的文章里头扒的:
public void cancelOrder(String username, Long orderId) {
// Check authorization on account
Order order = brokerageAccountRepository.findOrder(orderId);
checkAccountAuthorization(
getUser(username),
order.getAccount().getId(),
BrokerageAccountPermission.Trade);
// Cancel order
order.pendingCancel(orderEventPublisher);
exchangeTradingService.cancelOrder(order);
}
这个函数做的事情:输入username
和orderId
两个值对象,从brokerageAccountRepository
这个infrastructure层的对象里identify到唯一的order
Domain=》检查账户的认证状态(这个我也不好说,调用了很多东西,很乱……)=》调用order
Domain来取消订单=》从exchangeTradingService
里面取消订单,这个不讨论。
根据上面这个函数,总结两点:1、该应用层的函数通过一个值对象,到infra层去检索一个聚合
。2、该应用层的函数还能操作这个检索到的聚合
,触发一些domain层的事情,就像上面提到的 order.pendingCancel(orderEventPublisher)
这是DDD的重中之重,这个Domain跟建模时候那个Domain是两码事,这个放在第三小节展开了讲。
4、Domain层
因为Domain层是整个软件设计的核心部分,所以展开单独分配一小节来讨论。
这个写的好:Aggregates & Entities in Domain-Driven Design
举个例子:一个订单purchase order(PO)可能包含多个订单项Line items. 比如说结个婚要包含五金、彩礼、车子、房子啥的,一个道理。 聚合支持更高程度的概念。line items可以单独用,但是没啥意义。而且line items可能粒度太小,太麻烦。
这个我觉得说的挺好,一个PO是由entity和好多value object组成的一个聚合aggregate。这里面,PO这个entity是这个聚合的根。
业务逻辑被绑定在值对象上,而非实体上,实体更多地用来做identify。
一个聚合可能包含多个实体,比如说一个账户聚合可能包含一个账户实体和多个交易实体,通过定义事务边界来涵盖一个客户的存款/取款动作。
identify
是啥意思:ChatGPT查了一下,差不多就是说不管实体中的值对象怎么变化,实体的身份不会变。就好像一个客户,包含电子邮箱、资产啥的都会变,但是客户就是客户,不会变成摩托车或者油轮什么的。
我上面划掉的这句话的理解不太对,identify就像一本书的isbn号似的,唯一确定一个实体。
GoogleGroup的一个讨论
实体:域内具有重要意义(例如客户)并且可以随时间变化的唯一对象
值对象:域内的不可变对象,在其属性(例如日期、地址)之外没有任何意义
聚合:通过根对象相互关联的实体或值对象的集合
聚合根:“拥有”聚合并充当聚合内所有修改的网关的实体
What’s the Difference Between an Aggregate and a Bounded Context 这个文章太深了。。。
什么是域逻辑? 这个我也没看明白。。。
5、适用于DDD的设计模式等技术
Event Sourcing Example & Explained in plain English 源码收费,想给他个大逼斗,给我死。
Why Event Sourcing? 这个是有关于一个叫eventuate local的微服务开源框架的,这一篇有点儿用,剩下都是废话;
记录事件,用replay事件的方式去重组实体entity。作为消息的载体,允许services去订阅这些事件。事件存储是事件驱动结构的支柱。
Event Sourcing 这个太早了。05年的,不一定有用。
将应用程序的状态的所有更改都存储为事件序列……前面都是老调重弹;
Structuring the Event Handler Logic(构建事件处理的逻辑)这个没人提到过:事务脚本/域模型是什么勾巴东西?!
事件逆转:把+10美元变成-10美元,感觉这个水ppt挺有用的……
…………………………还有一些奇怪的点,都看完估计我就困了,主要看示例吧。
Event Sourcing in Go 写的不好,都是代码片段,不看了。
6、ES相关的开源package
Benthos
其它
DDD与es之间的联系;
事件溯源与事件驱动之间的区别和关系:
写一个基于我们的新系统的例子;