• 【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可以淡化。

  • 相关阅读:
    Sublime keymap 个性修改
    Sublime setting 个性修改
    微信公众接口测试频道
    Thinkphp 架构笔记
    mac ssh 远程容易断线解决方案
    日期按日、周、月 递增
    Centos Apache 多站点配置
    tar解压
    mac 将本地文件上传到vps
    ssh 连接vps
  • 原文地址:https://www.cnblogs.com/daoqidelv/p/8522502.html
Copyright © 2020-2023  润新知