同事问我代码结构中 Manager层是干什么的

6,245 阅读6分钟

这是我参与11月更文挑战的第18天,活动详情查看:2021最后一次更文挑战

写在前面

今天我们聊聊Manager,大家可能懵逼了,这是什么,这跟三层模式有关系,欢迎大家看我之前写过的一篇

周六加完班,聊聊MVC思想模式

聊manager之前再回顾下经典的三层模式

MVC(Model-View-Controller)架构。它将整体的系统分成了 Model(模型),View(视图)和 Controller(控制器)三个层次,也就是将用户视图和业务处理隔离开,并且通过控制器连接起来,很好地实现了表现和逻辑的解耦,是一种标准的软件分层架构。

image.png

MVC分层架构是架构上最简单的一种分层方式。为了遵循这种分层架构我们在构建项目时往往会建立这样三个目录:controller、service 和 dao,它们分别对应了表现层、逻辑层还有数据访问层。

这就是我们平常开发中一直遵循的开发原则,回顾完MVC分层方式,接下来进入正题讲讲Manager层。

Manager

最早定义该层的应该出自阿里开发规约中。

我们先来看副图,将Manager层融入到三层模式当中是怎样的一种结构(此图来源于阿里规约)

image.png

对比上述图我们一一作出解释

  • 开放接口层:可直接封装 Service 方法暴露成 RPC 接口;通过 Web 封装成 http 接口;网关控制层等。

  • 终端显示层:各个端的模板渲染并执行显示的层。当前主要是 velocity 渲染,JS 渲染,JSP 渲染,移动端展示等。

  • Web 层:主要是对访问控制进行转发,各类基本参数校验,或者不复用的业务简单处理等

  • Service 层:相对具体的业务逻辑服务层。

接下来解释Manager层

  • Manager 层:通用业务处理层,它有如下特征:

    1)对第三方平台封装的层,预处理返回结果及转化异常信息。

    2)对 Service 层通用能力的下沉,如缓存方案、中间件通用处理。

    3)与 DAO 层交互,对多个 DAO 的组合复用。

  • DAO 层:数据访问层,与底层 MySQL、Oracle、Hbase、OB 等进行数据交互。

  • 外部接口或第三方平台:包括其它部门 RPC 开放接口,基础平台,其它公司的 HTTP 接口。

总之一句话:在这个分层架构中主要增加了 Manager 层,它与 Service 层的关系是:Manager 层提供原子的服务接口,Service 层负责依据业务逻辑来编排原子接口。

说到这里 先不往下讲。我们先思考一个问题 就是MVC模式有什么弊端,为什么或者说Manager出现的意义

Manager出现的意义

其实仔细想想,传统的MVC分层有以下几个很明显的问题:

1) 由于我们Controller层不写任何业务逻辑 慢慢的导致Service层代码臃肿

2) 逻辑多起来之后,Service层很容易出现大事务,事务嵌套,导致问题很多,而且极难排查

3)那么逻辑会出现下沉,dao层参杂业务逻辑

4)dao层sql语句复杂,关联查询比较多

针对这些问题。Manager层应运而生。

我在哪看到这样一句话,感觉适用于所有的难题:大概意思就是 没有解决不了的问题,如果有 那就再抽一层,没有什么是抽层解决不了的问题

下面我们用实战案例演示一把。

Manager使用案例

这里我们举个例子说明一下Manager层的使用场景:

假设你有一个用户系统,他有一个获取用户信息的接口,它调用逻辑Service层的 getUser 方法,getUser方法又和 User DB 交互获取数据。

这时,善变的产品提出一个需求,在 APP 中展示用户信息的时候,如果用户不存在,那么要自动给用户创建一个用户

1) 此时按照传统的三层架构,逻辑层的边界就变得不清晰,表现层也承担了一部分的业务逻辑,因为我们往往会在表现层Service中增加业务逻辑处理,将获取用户和创建用户接口编排起来。

2)而添加Manager层以后,Manager 层提供创建用户和获取用户信息的接口,而 Service 层负责将这两个接口组装起来。这样就把原先散布在表现层的业务逻辑都统一到了 Service 层,每一层的边界就非常清晰了。

接下来我们看一段实际代码说明一下Service层与Manager层如何进行区分?


@Transactional(rollbackFor = Throwable.class)
public Result<String> upOrDown(Long departmentId, Long swapId) {
  // 验证 1
  DepartmentEntity departmentEntity = departmentDao.selectById(departmentId);
  if (departmentEntity == null) {
    return Result.error("部门xxx不存在");
  }
  // 验证 2
  DepartmentEntity swapEntity = departmentDao.selectById(swapId);
  if (swapEntity == null) {
    return Result.error("部门xxx不存在");
  }
  // 验证 3
  Long count = employeeDao.countByDepartmentId(departmentId);
  if (count != null && count > 0) {
    return Result.error("员工不存在");
  }
  
  // 操作数据库 4
  Long departmentSort = departmentEntity.getSort();
  departmentEntity.setSort(swapEntity.getSort());
  departmentDao.updateById(departmentEntity);
  swapEntity.setSort(departmentSort);
  departmentDao.updateById(swapEntity);
  return Result.OK("success");
}

上面代码在我们在我们采用三层架构时经常会遇到,那么它有什么问题呢?

就如我们上面所说的,逻辑太多会Service会及其臃肿,而且会非常引起事务套引起事务失效问题,

我们在加入Manager层以后可以这样写:

DepartmentService.java
  
public Result<String> upOrDown(Long departmentId, Long swapId) {
  // 验证 1
  DepartmentEntity departmentEntity = departmentDao.selectById(departmentId);
  if (departmentEntity == null) {
    return Result.error("部门xxx不存在");
  }
  // 验证 2
  DepartmentEntity swapEntity = departmentDao.selectById(swapId);
  if (swapEntity == null) {
    return Result.error("部门xxx不存在");
  }
  // 验证 3
  Long count = employeeDao.countByDepartmentId(departmentId);
  if (count != null && count > 0) {
    return Result.error("员工不存在");
  }
  
  // 操作数据库 4
  departmentManager.upOrDown(departmentSort,swapEntity);

  return Result.OK("success");
}
DepartmentManager.java
  
@Transactional(rollbackFor = Throwable.class)
public void upOrDown(DepartmentEntity departmentEntity ,DepartmentEntity swapEntity){
  Long departmentSort = departmentEntity.getSort();
  departmentEntity.setSort(swapEntity.getSort());
  departmentDao.updateById(departmentEntity);
  swapEntity.setSort(departmentSort);
  departmentDao.updateById(swapEntity);
}

将数据在 service 层准备好,然后传递给 manager 层,由 manager 层添加@Transactional事务注解进行数据库操作。

OK 今天我们关于Manager 就讲到这里,大家以后也可以在代码中运用起来。

总结

Manager 虽然让结构更清晰,但是不要一味的运用,逻辑复杂的时候可以考虑运用,我上面举例的可能相对简单 但是这是一种实践思想,合理运用,不要让代码显得更乱。

弦外之音

感谢你的阅读,如果你感觉学到了东西,您可以点赞,关注。也欢迎有问题我们下面评论交流

加油! 我们下期再见!

给大家分享几个我前面写的几篇骚操作

copy对象,这个操作有点骚!

干货!SpringBoot利用监听事件,实现异步操作