【DDD】领域驱动设计实践 —— 一些问题及想法
在社区系统的DDD实践过程中,将遇到一些问题和产生的想法记录下来,共讨论。
本文为【DDD】系列文章中的其中一篇,其他内容可参考:使用领域驱动设计思想实现业务系统。
1、dto、model和entity之间的互相转化
user interface层的dto、domian层的model、infrastructure层的entity之间的互相转换,比较繁琐,硬编码容易出错。
如果命名较为规范,则可以考虑交给一个公共服务完成自动转换,约定俗成:dto和model为驼峰式命名,entity和数据库表保持一致,使用小写字母+下划线形式,可以考虑编写一个工具服务完成自动映射;
现实情况下,社区系统是一个遗留系统,代码规范不佳,因此通用工具服务不可行。
2、repository的实现
针对不同的存储介质建议有不同的repository impl,比如rdb使用mybatis实现的dao,mongo有自己的dao;这些dao均需要实现domain层的Repository接口;
对于redis,通常用做缓存,它会搭配主存(rdb、mongo)使用,这时候,可以有一个RepositoryImpl实现类来包装 缓存/主存之间的增删改查逻辑。
例如:
com.eco.domain.repository.IUserRepository
public interface IUserRepository { public UserInfo queryUserInfoByUserId(long userId); }
@Repository
public class UserRepository implements IUserRepository {
@Autowired
private JedisCluster jedisCluster; @Autowired
private UserMapper userMapper; @Autowired
private UserRespostoryTranslator userRespostoryTranslator; @Override
public UserInfo queryUserInfoByUserId(long userId) {
UserRedisBean userRedisBean = this.queryUserRedisBeanByUserId(userId);
return this.userRespostoryTranslator.translateFromUserRedisBean(userRedisBean);
} private UserRedisBean queryUserRedisBeanByUserId(long userId) {
UserRedisBean userRedisBean = null;
// 获取缓存key
String userIdKey = RedisKeyUtil.getRedisKey(RedisTypeEnum.UserInfoByUserId, StringUtil.toString(userId));
String value = jedisCluster.get(userIdKey); // redis中不存在,则从db中获取用户相关信息
if (StringUtil.isEmpty(value)) { // 根据userid及用户社交对象从oracle查询用户信息
userRedisBean = getUserRedisBeanFromOracle(userId); if (userRedisBean != null) {
// 用户信息写入redis
JedisClusterUtil.set(jedisCluster, userIdKey, JsonUtil.toJSONString(userRedisBean),ConfigurationConst.userRedisSeconds);
}
} else {
// 如果redis中存在,则从redis获取用户相关信息,并设置有效期
userRedisBean = JsonUtil.parseObject(value, UserRedisBean.class);
}
return userRedisBean;
} /**
* 根据userid从oracle查询用户信息
*
* @param userId
* @return UserRedisBean 欲存入redis中的用户信息bean
*/
private UserRedisBean getUserRedisBeanFromOracle(long userId) { UserRedisBean userRedisBean = null; // 根据userid查询用户信息
UserInfo userInfo = this.queryUserInfoByUserIdFromOracle(userId); //ignore transfer UserInfo to UserRedisBean.
return userRedisBean;
}
}
3、查询式和命令式接口使用的domain需要分离
查询式接口domain应当简化,甚至于去掉。通常查询接口的实现逻辑为:入参校验、鉴权、从Repository中获取数据、拼凑不同的数据、数据转换、返回数据。理论上,不应当存在过多的业务逻辑。所以可以淡化domain层。如果仍然按照:entity --> model -->dto的转换路径,实际model的作用没有,反而带来了代码复杂度,不值得。
命令式接口,除去查询式接口的逻辑,还有部分业务相关的,比如“关注”这一业务逻辑,较为复杂,需要收口到domain。
因此,建议如下处理方式:
查询式和命令式接口使用的domain需要分离设计,查询式接口使用的domain可以淡化。
【DDD】领域驱动设计实践 —— 一些问题及想法的更多相关文章
- DDD领域驱动设计和实践(转载)
-->目录导航 一. DDD领域驱动设计介绍 1. 什么是领域驱动设计(DDD) 2. 领域驱动设计的特点 3. 如果不使用DDD? 4. 领域驱动设计的分层架构和构成要素 5. 事务脚本和领域 ...
- DDD 领域驱动设计-谈谈 Repository、IUnitOfWork 和 IDbContext 的实践(3)
上一篇:<DDD 领域驱动设计-谈谈 Repository.IUnitOfWork 和 IDbContext 的实践(2)> 这篇文章主要是对 DDD.Sample 框架增加 Transa ...
- DDD 领域驱动设计-谈谈 Repository、IUnitOfWork 和 IDbContext 的实践(2)
上一篇:<DDD 领域驱动设计-谈谈 Repository.IUnitOfWork 和 IDbContext 的实践(1)> 阅读目录: 抽离 IRepository 并改造 Reposi ...
- DDD 领域驱动设计-谈谈 Repository、IUnitOfWork 和 IDbContext 的实践(1)
好久没写 DDD 领域驱动设计相关的文章了,嘎嘎!!! 这几天在开发一个新的项目,虽然不是基于领域驱动设计的,但我想把 DDD 架构设计的一些东西运用在上面,但发现了很多问题,这些在之前的短消息项目中 ...
- DDD 领域驱动设计-谈谈 Repository、IUnitOfWork 和 IDbContext 的实践(转)
http://www.cnblogs.com/xishuai/p/ddd-repository-iunitofwork-and-idbcontext.html 好久没写 DDD 领域驱动设计相关的文章 ...
- 【DDD】领域驱动设计实践 —— UI层实现
前面几篇blog主要介绍了DDD落地架构及业务建模战术,后续几篇blog会在此基础上,讲解具体的架构实现,通过完整代码demo的形式,更好地将DDD的落地方案呈现出来.本文是架构实现讲解的第一篇,主要 ...
- DDD领域驱动设计落地实践(十分钟看完,半小时落地)
一.引子 不知今年吹了什么风,忽然DDD领域驱动设计进入大家视野.该思想源于2003年 Eric Evans编写的"Domain-Driven Design领域驱动设计"简称DDD ...
- 浅谈我对DDD领域驱动设计的理解
从遇到问题开始 当人们要做一个软件系统时,一般总是因为遇到了什么问题,然后希望通过一个软件系统来解决. 比如,我是一家企业,然后我觉得我现在线下销售自己的产品还不够,我希望能够在线上也能销售自己的产品 ...
- DDD领域驱动设计之领域服务
1.DDD领域驱动设计实践篇之如何提取模型 2.DDD领域驱动设计之聚合.实体.值对象 3.DDD领域驱动设计之领域基础设施层 什么是领域服务,DDD书中是说,有些类或者方法,放实体A也不好,放实体B ...
随机推荐
- 华为交换机boot默认密码
交换机系统启动bootrom时,在2秒内按下"CTRL+B",此处需要输入密码才能进入BOOTROM菜单.默认密码如下: 1. S9300 V100R006及其之前的版本:9300 ...
- linux的定时任务服务crond(crontab)服务
1,Crond: Crond是linux系统中用来定期执行命令或指定程序任务的一种服务或者软件.(Centos5以后默认存在) 当优化开机自启动的时候,第一个就是crond. Crond服务默认情况( ...
- [PHP]接口请求校验的原理
具体的校验步骤可以自定义,下面是比较直观的一种形式: 1. 客户端:请求参数带上时间,进行首字母排序,连接私钥后,取得加密结果: 客户端请求时带上这个加密结果作为sign参数. 2. 服务端:对sig ...
- jmeter用Firefox录制https协议证书问题解决
录制脚本的时候,比如录制https协议的百度网站 https://www.baidu.com ,所有录制设置均正常,但是在jmeter录制控制器里面就是没有任何录制的请求. 这个时候提示说证书不对 1 ...
- python中的列表排序
对列表进行排序是常见的操作,最简单的方式是使用sort()函数. 1.一般用法 不管列表元素是数.字符串还是元组,函数sort()总是就地操作列表,按升序进行排列元素,并返回None. #数 > ...
- Go笔记-map
[概念] 1- map 是引用类型的 2- 声明方式 var map1 map[keytype]valuetype 例如:var map1 ma ...
- 策略模式(Strategy Method)
策略模式可以看做“可插入式算法(Pluggable)”,将子类各自的行为和公共的逻辑分离开来,将子类的行为抽象为算法插入到公共的逻辑中,这样替换子类的行为也不会对公共逻辑产生影响,也不会影响到调用类的 ...
- BZOJ 1593: [Usaco2008 Feb]Hotel 旅馆 [线段树]
传送门 题意: 操作1:找长为$len$的空区间并填满,没有输出$0$ 操作2:将$[l,r]$之间的区间置空 我真是太弱了这种线段树还写了一个半小时,中间为了查错手动模拟了$30min$线段树操作, ...
- 对.Net Core结合Docker和Jexus的实践
本文基于上次尝试之后的进一步尝试,加入Docker容器.编写Dockerfile,并且jexus结合Docker的使用,总结下自己的个人感想. 一.环境介绍 当前的场景有两种方式将Demo实现运行,一 ...
- Centos7搭建FTP服务器
从网上搜索了好多搭建Centos7搭建服务器的教程都没有成功唯独这个,利用Windows资源管理器连接测试成功. 一.通过yum安装vsftpd yum install -y vsftpd 二.修改v ...