【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
1 2 3 4 5 | public interface IUserRepository { public UserInfo queryUserInfoByUserId( long userId); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | @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.<br> return userRedisBean; }<br>} |
3、查询式和命令式接口使用的domain需要分离
查询式接口domain应当简化,甚至于去掉。通常查询接口的实现逻辑为:入参校验、鉴权、从Repository中获取数据、拼凑不同的数据、数据转换、返回数据。理论上,不应当存在过多的业务逻辑。所以可以淡化domain层。如果仍然按照:entity --> model -->dto的转换路径,实际model的作用没有,反而带来了代码复杂度,不值得。
命令式接口,除去查询式接口的逻辑,还有部分业务相关的,比如“关注”这一业务逻辑,较为复杂,需要收口到domain。
因此,建议如下处理方式:
查询式和命令式接口使用的domain需要分离设计,查询式接口使用的domain可以淡化。
*****************************************************************************************
********************* 联系方式:qq:464675856; email: huyangleng3684@sina.com **********************
********** 微信个人账号:mr_daoqi ************ ************* 微信公众号:倒骑的驴 **************
*****************************************************************************************
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了