page contents

我想要在repository中调用service

Pack 发布于 2019-12-24 16:24
阅读 854
收藏 0

场景描述

不管是分布项目还是在单体结构,模块划分都是一个很重要的工作。
模块和模块之间,层和层之间,屏蔽一些细节,也是一个良好的设计标准。
细节…
比如User模块和Course模块,课程模块因为需要选课,要依赖于用户模块。
对于Course模块的核心逻辑来说,User模块是在远程还是在本地,就是一个需要屏蔽的细节。
我的问题就是怎么屏蔽??

图解说明

  • 我的划分是颗粒度最小的划分,按业务模块和层同时划分
  • 图例的实心箭头表示调用,空心箭头表示实现
  1. 模块关系图
    attachments-2019-12-KTHWO7Ms5e01cd4411c40.png
  2. 块内的组件图

attachments-2019-12-RVuzQqsx5e01cbaa9b030.jpg

  1. 组件调用图
    attachments-2019-12-LtxrLHEe5e01cbc10ab7a.jpg

ps:虽然包多了不好管理,但是基本符合SRP、OCP、LSP、ISP、DIP

好处

这样做是有好处的,除去最下层的CourseClient用于组装,上层的所有Coure组件,都不需要了解用户的细节,只需要知道User的API就可以了
比如选课的时候,只有在学的学生才能选课,直接调用UserService的isInSchool(userId)就判断了,至于是去远程判断还是本地判断CourseService不需要关心

问题

查询往往比增删改更加复杂,简单查询还好,如果是复杂的批量查询,比如一次查出选了课程A的所有学生信息,问题就来了,本地和远程是有区别的。

  1. 问题1:性能区别
    当然,你可以查出根据课程id查出所有的用户Id,然后调用UserService.getById或者UserService.getByIds方法获取用户信息,如果是远程服务,只能这样,但是如果本地,用户表和选课表都在一个库了,这样会大费周折,浪费性能,这个我们不能不关心吧。

  2. 问题2:调用的时机
    也是标题的问的问题。就简单查询的情况,查询一个选课的信息,其中要包含User对象,更具ORM的原则,我们在repository中查询返回的是一个选课对象,选课中包含用户信息

/**

 * 选课的信息

 */

public class Elective {

    private long id;

    private Course course;

    private User user;


    ... ...

/*

 * 选课操作

 */

public interface ElectiveRepository {


    Elective getById(long id);


    ... ...

如果在service获取Elective,然后判断Elective 中是否有用户详细信息(因为远程User的情况下,简单的ElectiveRepositoryImpl无法直接获取用户详细信息,只能获取UserId),那么远程的细节就没有被真正的屏蔽掉。

  1. 问题3:复杂搜索
    就算是我们不考虑性能,如果遇到复杂的情况,比如,查询所有选了课程A的所有学生中,2年级的学生。如果本地部分模块的话,我们可以调用关系数据库进行关联查询,如果是远程,就不能这么简单的做了

思路

增加不同实现解决调用时机和性能问题

  • 就第一二个问题的思路,又要考虑性能,有要考虑隔离,中间可以做一个权衡。
  • 没有办法彻底隔离就不隔离,但是最好不要污染核心逻辑(service层以及service实现)
  • 使用下沉,把具体细节下沉到Repository的实现中,让CourseClient去选择
  • attachments-2019-12-yDtF9twJ5e01cbfeb6973.jpg
    也就是通过增加复杂度来解决问题
  • 远程对于repository来说,就是一种存储,像Mysql一样
  • 但是就出现了在repository中调用service的问题

复杂查询

  • 第三个复杂查询的,似乎远程的没有好办法,只能增加一个查询系统,来调用了。结合上面的,在CourseRepositoryImplLocal中,维护查询系统,调用搜索

所以

所以两个问题

  1. 上面的狗屁通吗?
  2. 在repository中调用service合理吗?
11
Pack
Pack

我看了你的思考过程,挺好的。

你的整个思考过程都在迎合SRP、OCP、LSP、ISP、DIP等设计原则。 有点过度设计的意思。

首先这些设计原则是标准模型,在很多实际开发过程中,会有很多非标类的情况,所以适当设计才能更好的落地


第二个问题,repository调用service肯定是不合理的。

请先 登录 后评论