对领域模型DDD的理解

领域驱动设计(DDD Domain-Drivern-Design)

当下敏捷开发备受各大公司推崇,在需求快速迭代的过程中必然会对代码有所腐坏,增加维护的难度。微服务的大环境下,我们就需要一个更有套路的设计方式,DDD就是其中之一。

演进

在这里插入图片描述
注:
DDD和MVC并非互斥的,在DDD项目中,针对一些直接读库的操作。也可以沿用MVC设计,直接从应用层直接调用基础数据层获取。

贫血模式和充血模式

贫血模式:只赋予get、set等方法,单纯的做数据的载体。
优点:将业务逻辑分离出去,降低系统耦合。
缺点:只有属性,没有行为的对象是不具有生命的,不符合OOP的思想,是阉割版本。增加了业务层的复杂度。

@Data
@Table(name = "t_user")
public class UserDDD {
    @Id
    @KeySql(useGeneratedKeys = true)
    private Long id;
    private String username;
    private String password;
}

充血模式:不仅仅包含set、get方法,还提供一系列创建、修改、检查、计算等方法
优点:既有属性,又有行为,是完整的对象,符合OOP的思想。
缺点:在实际运用中难以完全区分业务和对象的行为。

@Data
@Table(name = "t_user")
public class UserDDD {
    @Id
    @KeySql(useGeneratedKeys = true)
    private Long id;
    private String username;
    private String password;

    public static void check(OpenUser openUser) {
        // do check
        return;
    }
    public static User InitUser(OpenUser openUser){
        check(openUser);
        User user = new User();
        user.setPassword(openUser.getPassword());
        user.setUsername(openUser.getUsername());
        return user;
    }
}

DDD的示例代码

在这里插入图片描述

视图层/API层/consumer

// 目录 import com.company.teamname.login  登录微服务
@Slf4j
@RestController
@RequestMapping("user")
public class UserController {

    @Autowired
    private ILoginService loginService;
    @RequestMapping("/toLogin")
    public ModelAndView ToLogin() {
        ModelAndView mv = new ModelAndView();
        //存入
        mv.setViewName("/login.html");
        //返回test.html
        return mv;
    }
}

应用层-调用多个domain

// 应用层,依赖领域层和基础数据层
// 目录 import com.company.teamname.login.user.service
@Service
public class LoginService {
    @Autowired
    private IUserImpl userImpl;
    @Autowired
    private IRoleImpl roleImpl;
    public void createUser(int id) {
        UserContext context = UserContext.initContext(id);
        userImpl.getRoleIdAndUpdateLoginTime(context);
        RoleContext roleContext = RoleContext.initContext(context.GetRoleId());
        roleContext.checkPermission(roleContext);
    }
}

领域界限上下文

// DTO  用户上下问
// 目录 import com.company.teamname.login.user  登录微服务-用户模块上下文
@Data
class UserContext {
    private int id;
    private int roleId;
    
    public static UserContext initContext(int id) {
        UserContext context = new UserContext(); 
        context.setId(id);
        return context;
    }
    
}

领域层-领域服务

// 应用层,依赖领域层和基础数据层
// 目录 import com.company.teamname.login.user.service
@Service
public class LoginService {
    @Autowired
    private IuserDaoImpl userDao;

    public void getRoleIdAndUpdateLoginTime(UserContext context) {
    	User user = baseDao.getUserById(context.GetId());
        // do some thing
        user.refreashLoginTime();
        baseDao.update("UserMapper.updateModel", user);
        context.setRoleId(user.GetRoleId());
    }
}

领域层-领域对象

// 目录 import com.company.teamname.login.user.domain
import com.company.teamname.login.user.domain.entity
// 对外暴漏封装好的操作对象的方法,只包含基础包,不能引入任何注解依赖,以便可以移植到任何项目中都不报错
// DO
@Data
public class UserDDD {
    private String username;
    private String password;
    private int roleId;
	private int loginTime;
    public void check(UserContext context) {
        // do check
        return;
    }
    public void refreashLoginTime(){
		this.loginTime = now();
	}
	public void setRoleId(UserContext context){
		context.SetRoleId(this.roleId);
	}
}

Interface  UserDao {
}

领域层-基础数据库

// 目录 import com.company.teamname.login.user.repo
// 可以在查询同时实现一些缓存等逻辑
class IuserDaoImpl Impl  UserDao {}

领域层-数据防腐

// 目录 import com.company.teamname.login.user.facade  登录业务的用户模块上下文
// 由于UserContext在某些场景下,需要访问外部上下文获取数据,采用防腐层进行转义,防止外部APi变更导致我们跟着批量变更
@Component
class PressAddress {
	@Autowired
	private addressService IAddressService;
	
	public CityInfo getCity(UserContext context){
		City city = addressService.transformCity(xxx);
		return buildCityInfo(city);
	}
	
	public CityInfo buildCityInfo(City city){
		// xxx
	}
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值