【DDD】領域驅動設計實踐 —— 一些問題及想法

在社區系統的DDD實踐過程當中,將遇到一些問題和產生的想法記錄下來,共討論。html

本文爲【DDD】系列文章中的其中一篇,其餘內容可參考:使用領域驅動設計思想實現業務系統java

一、dto、model和entity之間的互相轉化redis

user interface層的dto、domian層的model、infrastructure層的entity之間的互相轉換,比較繁瑣,硬編碼容易出錯。數據庫

若是命名較爲規範,則能夠考慮交給一個公共服務完成自動轉換,約定俗成:dto和model爲駝峯式命名,entity和數據庫表保持一致,使用小寫字母+下劃線形式,能夠考慮編寫一個工具服務完成自動映射;緩存

現實狀況下,社區系統是一個遺留系統,代碼規範不佳,所以通用工具服務不可行。mybatis

二、repository的實現

針對不一樣的存儲介質建議有不一樣的repository impl,好比rdb使用mybatis實現的dao,mongo有本身的dao;這些dao均須要實現domain層的Repository接口;oracle

對於redis,一般用作緩存,它會搭配主存(rdb、mongo)使用,這時候,能夠有一個RepositoryImpl實現類來包裝 緩存/主存之間的增刪改查邏輯。app

例如:dom

 com.eco.domain.repository.IUserRepository ide

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; }
}

三、查詢式和命令式接口使用的domain須要分離

查詢式接口domain應當簡化,甚至於去掉。一般查詢接口的實現邏輯爲:入參校驗、鑑權、從Repository中獲取數據、拼湊不一樣的數據、數據轉換、返回數據。理論上,不該當存在過多的業務邏輯。因此能夠淡化domain層。若是仍然按照:entity --> model -->dto的轉換路徑,實際model的做用沒有,反而帶來了代碼複雜度,不值得。

命令式接口,除去查詢式接口的邏輯,還有部分業務相關的,好比「關注」這一業務邏輯,較爲複雜,須要收口到domain。

所以,建議以下處理方式:

  查詢式和命令式接口使用的domain須要分離設計,查詢式接口使用的domain能夠淡化。

相關文章
相關標籤/搜索