领域驱动分层实践

三类对象:DTO,领域对象,PO

一、分层参考

a、基础设施层infrastructure
--client
--common
--event
--api
--util

b、领域层

domain
leave
--entity
--valueobject(包含结构体,枚举等)
xxDomainObject(唯一标识,字段,方法 return this 操作属性集合)
--event
xxEvent
xxEventType
--repository
facade
xxInterface
mapper
xxDao
persistence
xxRepositoryImpl
po
xxPO
--service
xxService(返回具体的领域对象)
xxFactory (领域对象与PO对象转换)重要创建Factory***

c、聚合服务层

application.service
xxxService (聚合层服务,领域服务编排,操作领域对象)

d、对外接口层 interfaces
--assembler (领域对象与DTO转换)
--dto
--facade
xxApi

---------------------------------------
xxDomainObject示例

@Data
public class Leave {

String id;
Applicant applicant;
Approver approver;
LeaveType type;
Status status;
Date startTime;
Date endTime;
long duration;
//审批领导的最大级别
int leaderMaxLevel;
ApprovalInfo currentApprovalInfo;
List<ApprovalInfo> historyApprovalInfos;

public long getDuration() {
return endTime.getTime() - startTime.getTime();
}

public Leave addHistoryApprovalInfo(ApprovalInfo approvalInfo) {
if (null == historyApprovalInfos)
historyApprovalInfos = new ArrayList<>();
this.historyApprovalInfos.add(approvalInfo);
return this; //重点返回this
}

xxEvent示例

@Data
public class LeaveEvent extends DomainEvent {

LeaveEventType leaveEventType;

public static LeaveEvent create(LeaveEventType eventType, Leave leave){
LeaveEvent event = new LeaveEvent();
event.setId(IdGenerator.nextId());
event.setLeaveEventType(eventType);
event.setTimestamp(new Date());
event.setData(JSON.toJSONString(leave));
return event;
}
}


common.event
@Data
public class DomainEvent {

String id;
Date timestamp;
String source;
String data;
}

xxService示例

@Transactional
public void submitApproval(Leave leave, Approver approver) {
LeaveEvent event;
if ( ApprovalType.REJECT == leave.getCurrentApprovalInfo().getApprovalType()) {
//reject, then the leave is finished with REJECTED status
leave.reject(approver);
event = LeaveEvent.create(LeaveEventType.REJECT_EVENT, leave);
} else {
if (approver != null) {
//agree and has next approver
leave.agree(approver);
event = LeaveEvent.create(LeaveEventType.AGREE_EVENT, leave);
} else {
//agree and hasn't next approver, then the leave is finished with APPROVED status
leave.finish();
event = LeaveEvent.create(LeaveEventType.APPROVED_EVENT, leave);
}
}
leave.addHistoryApprovalInfo(leave.getCurrentApprovalInfo());
leaveRepositoryInterface.save(leaveFactory.createLeavePO(leave));
leaveRepositoryInterface.saveEvent(leaveFactory.createLeaveEventPO(event));
eventPublisher.publish(event);
}

xxApi示例

@GetMapping("/findFirstApprover")
public Response findFirstApprover(@RequestParam String applicantId, @RequestParam int leaderMaxLevel) {
Person person = personApplicationService.findFirstApprover(applicantId, leaderMaxLevel);
return Response.ok(PersonAssembler.toDTO(person));
}


------------------------------------------------------------------------------------------------------------------

调单系统代码研究

1、6边形架构

外6边形(技术域)
in:定时任务、Web接入点、RPC接入点、MQ消费者
out:MQ适配器、RPC适配器、仓库(mysql、redis、lucence.net)

内6边形(业务域)
应用服务->创建工厂->创建领域对象(聚合根、实体、值对象、事件)
-----更新-----领域对象(聚合根、实体、值对象、事件)

2、Assembler
1、负责PO对象与领域对象转换
2、负责Active当前对象与存量对象转换
3、复杂对象组成方式

@Slf4j
@Service
public class BatchManipulateCollectsRequestAssembler {
private final BatchManipulateCollectionBuilderFactory batchManipulateCollectionBuilderFactory;
private final CollectionBuilderFactory collectionBuilderFactory;
private final UpdateCollectionBuilderFactory updateCollectionBuilderFactory;
private final FinishCollectionBuilderFactory finishCollectionBuilderFactory;
private final TerminateCollectionBuilderFactory terminateCollectionBuilderFactory;

@Autowired
public BatchManipulateCollectsRequestAssembler(BatchManipulateCollectionBuilderFactory batchManipulateCollectionBuilderFactory,
CollectionBuilderFactory collectionBuilderFactory,
UpdateCollectionBuilderFactory updateCollectionBuilderFactory,
FinishCollectionBuilderFactory finishCollectionBuilderFactory,
TerminateCollectionBuilderFactory terminateCollectionBuilderFactory) {
this.batchManipulateCollectionBuilderFactory = batchManipulateCollectionBuilderFactory;
this.collectionBuilderFactory = collectionBuilderFactory;
this.updateCollectionBuilderFactory = updateCollectionBuilderFactory;
this.finishCollectionBuilderFactory = finishCollectionBuilderFactory;
this.terminateCollectionBuilderFactory = terminateCollectionBuilderFactory;
}

xxFactroy: 检验器xxxValidator + xxxBuilder.create()方法

@Component
public class BatchManipulateCollectionBuilderFactory {

private final FieldsFormatValidator fieldsFormatValidator;

public BatchManipulateCollectionBuilderFactory(FieldsFormatValidator fieldsFormatValidator) {
this.fieldsFormatValidator = fieldsFormatValidator;
}

public BatchManipulateCollectionReqBuilder create() {
return new BatchManipulateCollectionReqBuilder(this.fieldsFormatValidator);
}
}

toDo(service层:领域对象),toDTO(control层:DTO),toPO(持久层:PO)

3、Sharding jdbc指定库表



@DS("cddcollect")
public interface TCollectManagerMapper extends CustomBaseMapper<TCollectManager> {


@Select({"<script> SELECT * from cdd_collect_${dbIndex}.t_collect_manager_${tabIndex} ",
"where Fwaiting_collection_count>0 ",
"limit 1000;",
"</script>"})
List<TCollectManager> queryShouldFuseCollectManager(@Param("dbIndex") String dbIndex,
@Param("tabIndex") String tabIndex);
}

4、ExceptionFactry 异常工厂

+bizException业务异常
+sysException系统异常
+retryableBizException 可重试异常

-----------------------------------------------------

内6边形(业务域)

应用服务->创建工厂->创建领域对象(聚合根、实体、值对象、事件)
-----更新-----领域对象(聚合根、实体、值对象、事件)


application:聚合服务层,负责领域服务的流程编排以及领域事件的发布

domain:具体领域,基于接口编程
- model 包含聚合根,实体、值对象、常量、请求参数类、返回参数类
- validate: 字段检验规则
- factory: 包含validate检验器,以及XxxBuilder.create()方法(生产者模式)
当创建领域对象时,调用build()方法,赋值Builder字段给领域对象时,前置先检验字段是否合法
- exception
- repository:定义接口
- serivce: 领域服务接口+具体实现

--------------------------------------------------------------------------------------------------------------------

外6边形(技术域)
in:定时任务、Web接入点、RPC接入点、MQ消费者
out:MQ适配器、RPC适配器、仓库(mysql、redis、lucence.net)

adapter

in:
mq消费者:
task定时任务:发件箱
web: 接口、运维接口

out
mq生产者:发布事件
仓库:mysql
RPC适配器:业务服务、配置服务、Qf发送消息服务、分布式锁(redis,zk)服务、发件箱服务

 

 

posted @   mick0802  阅读(31)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
点击右上角即可分享
微信分享提示