当前位置:   article > 正文

ddd领域驱动java_DDD- 领域驱动设计入门

java ddd demo

概述

去年4月份入职后第一次了解到DDD,当时觉得很晦涩(现在来看应该是红皮书将战略设计放在前半部分的缘由)。今年4月份的时候想学学系统设计方面的知识,便开始静下心来好好研究了两个月,感觉收益颇多。

DDD是什么

DDD是一种'面向对象'的软件设计思想。

领域驱动设计DDD作为一种软件设计方式, 有利于创造一个可测试的、可伸缩的、组织良好的软件模型

贫血症与失忆症

写Java差不多刚好两年, 接触过的项目中,几乎所有的业务逻辑都是写在service里面,对象都只是数据持有器(POJO),这些没有任何业务方法的对象就是贫血对象。

在这样的系统中,代码里面往往充斥者大量与业务无关的getter、setter方法,开发人员会将将大量的精力放在数据映射上面,而不是真正有价值的对象行为。

下面是一个更新用户的例子:

public void updateUser(String userId, String firstName, String lastName, String mobile,String address, Integer sex, String avator, ...) {

User user = new User();

if(userId != null) {

user.setUserId(userId);

}

if(firstName != null){

user.setFirstName(firstName);

}

if(lastName != null){

user.setLastName(lastName);

}

if(mobile != null){

user.setMobile(mobile);

}

if(address != null){

user.setAddress(address);

}

if(sex != null){

user.setSex(sex);

}

if(avator != null){

user.setAvator(avator);

}

...

userDao.updateUser(user);

}

复制代码

首先:这个方法的业务意图不明确。应用层应该一个方法对应一个明确的业务用例,如更新用户手机号, 更新居住地址等。

其次:方法的实现增加了潜在的复杂性。 我们应该怎么测试这段代码呐?这么多if, 你确定你能愉快的修改代码吗,内心是不是很排斥?

最后:User对象只是一个数据持有器。

这种情况也被称为由贫血症导致的失忆症。

如何DDD

通用语言

通用语言是团队之间用于交流的语言,一般指当前业务场景提炼出来的领域术语、词组和句子。比如绩效系统里"271排名"就是一种领域术语。

限界上下文

限界上下文可以看成是整个应用程序之内的一个概念性边界。这个边界之内的每种领域术语、词组或句子 --- 也即通用语言,都有确定的上下文含义。而在边界之外,这些术语可能有不同的意思。

比如盘点,当HR说盘点时是对员工进行盘点;而IT说盘点的时候,是对设备进行盘点。两者的上下文是完全不一样的,盘点的语义自然不同。

以日程管理系统开始DDD学习

部分用例

企业员工发起一个日程,包含日程的主题、开始时间、结束时间、参与人员。

发起人修改日程时间

参与人确认日程

员工查看自己当天的所有日程

传统面向过程的写法

/**

创建日程:1.日程表中插入一条记录, 2.人关联日程

**/

@Transactional

public void createSchedule(String title, Date startTime, Date endTime, List participantIds){

Long sponsorId = loginUser.get().getUserId();

//创建日程

Schedule schedule = new Schedule();

schedule.setTitle(title);

schedule.setStartTime(startTime);

schedule.setEndTime(endTime);

schedule.setSponsorId(sponsorId);

Long scheduleId = scheduelDao.insert(schedule);

//人关联日程

List userSchedules = new LinkedList();

for(participantId : participantIds){

userSchedules.add(new UserSchedule(participantId, scheduleId, 0));

}

if(!userSchedules.isEmpty()){

userScheduleDao.batchInsert(userSchedules);

}

}

复制代码

这样写其实也暴露了底层数据结构

DDD写法

日程对象

public class Schedule{

private String title;

private Date startTime;

private Date endTime;

private User sponsor;

Set participants;

Set confirmUsers;

Set refuseUsers;

/**

通过构造函数创建一个日程

**/

pubulic Schedule(String title, Date startTime, Date endTime, User sponsor, Set participants){

if(title == null || title == ""){

throw new IllegalArgumentException("schedule title empty");

}

if(startTime == null || endTime == null || !startTime.before(endTime)){

throw new IllegalArgumentException("schedule time range invalid.");

}

if(sponsor == null){

throw new IllegalArgumentException("schedule sponsor not found");

}

//remove duplicate

participants = participants.strem().filter(participant -> !participant.equals(sponsor)).collecot(Collectors.toSet());

this.title = title;

this.startTime = startTime;

this.endTime = endTime;

this.participants = participants;

}

/**

更新日程时间

**/

void updateTimeRange(Date startTime, Date endTime){

if(startTime == null || endTime == null || !startTime.before(endTime)){

throw new IllegalArgumentException("schedule time range invalid.");

}

this.startTime = startTime;

this.endTime = endTime;

}

/**

日程确认

**/

void confirm(User participant){

if(!this.participants.contains(participant)){

throw new IllegalArgumentException("you are not invited, can`t confirm");

}

if(this.confirmUsers.contains(participant)){

throw new IllegalArgumentException("you have confirmed");

}

this.confirmUsers.add(participant);

}

}

复制代码

应用层 -- ApplicationService

/**

创建日程

**/

@Transactional

public void createSchedule(String title, Date startTime, Date endTime, List participantIds){

Long sponsorId = loginUser.get().getUserId();

User sponsor = useRepository.userOfId(sponsorId);

List participants = useRepository.usersOfIds(participantIds);

Schedule schedule = new Schedule(title, startTime, endTime, sponsor, participants);

scheduleRepository.add(schedule);

}

/**

更新日程时间

**/

@Transactional

public void updateScheduleTime(Long scheduleId, Date startTime, Date endTime){

Schedule schedule = scheduleRepository.scheduleOfId(scheduleId);

schedule.updateTimeRange(startTime, endTime);

scheduleRepository.save(schedule);

}

/**

确定日程

**/

@Transactional

public void confirmSchedule(Long scheduleId){

Long userId = loginUser.get().getUserId();

User user = useRepository.userOfId(userId);

Schedule schedule = scheduleRepository.scheduleOfId(scheduleId);

schedule.confirm(user);

scheduleRepository.save(schedule);

}

复制代码

The end

通过上面日程管理的demo,你是否可以重构updateUser方法呐?

b739ec46bb5c46d9c0aa4ce35ba1ea56.png

关于找一找教程网

本站文章仅代表作者观点,不代表本站立场,所有文章非营利性免费分享。

本站提供了软件编程、网站开发技术、服务器运维、人工智能等等IT技术文章,希望广大程序员努力学习,让我们用科技改变世界。

[DDD- 领域驱动设计入门]http://www.zyiz.net/tech/detail-139677.html

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/380724
推荐阅读
相关标签
  

闽ICP备14008679号