在社區系統的DDD實踐過程當中,將遇到一些問題和產生的想法記錄下來,共討論。html
本文爲【DDD】系列文章中的其中一篇,其餘內容可參考:使用領域驅動設計思想實現業務系統。java
一、dto、model和entity之間的互相轉化redis
user interface層的dto、domian層的model、infrastructure層的entity之間的互相轉換,比較繁瑣,硬編碼容易出錯。數據庫
若是命名較爲規範,則能夠考慮交給一個公共服務完成自動轉換,約定俗成:dto和model爲駝峯式命名,entity和數據庫表保持一致,使用小寫字母+下劃線形式,能夠考慮編寫一個工具服務完成自動映射;緩存
現實狀況下,社區系統是一個遺留系統,代碼規範不佳,所以通用工具服務不可行。mybatis
針對不一樣的存儲介質建議有不一樣的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應當簡化,甚至於去掉。一般查詢接口的實現邏輯爲:入參校驗、鑑權、從Repository中獲取數據、拼湊不一樣的數據、數據轉換、返回數據。理論上,不該當存在過多的業務邏輯。因此能夠淡化domain層。若是仍然按照:entity --> model -->dto的轉換路徑,實際model的做用沒有,反而帶來了代碼複雜度,不值得。
命令式接口,除去查詢式接口的邏輯,還有部分業務相關的,好比「關注」這一業務邏輯,較爲複雜,須要收口到domain。
所以,建議以下處理方式:
查詢式和命令式接口使用的domain須要分離設計,查詢式接口使用的domain能夠淡化。