请问Repository这个概念如何理解啊

最近接手维护一个项目用到了prettus/l5-repository 这个库,里面涉及到了Repository Pattern这种设计模式,其中Repository 和 Criteria 这两个概念让我着实很费解。
主要是两方面
1、Repository感觉和DAO很像。比如Repository提供的一系列方法, getById findBy() 之类的,感觉做一个baseModel的父类继承一下也一样能实现,而且Repository这些方法本质上还是依赖于$this->model,即eloquent model来实现。不理解为什么要再划分出Repository的意义,而且Repository层还要绑定一层接口到实现,是为了便于更换数据源做单元测试之类的?
2、Criteria这个概念不知道中文用什么来表述。看上去有点像复用的条件组的概念,和 Scope 很像。
3、Fractal Presenter和 Transformer我就更搞不懂了。之前项目业务逻辑都是在service层处理的,从数据源返回数据后,通常就是根据接口输出的字段要求,循环做一些修饰和删减。有必要搞这么复杂吗?

现在这个项目代码分了这么多层,一条业务逻辑线拆的稀碎,接口到实现IDE追代码也十分不友好,写新的代码一开始要创建一大堆的文件,真是心累。

《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
sanders
最佳答案

平时没有用过,但谈一点我对仓库层的理解。

第一点是做数据访问的进一步抽象化,这方面可以考虑一个场景:

业务通过仓库获取数据的时候,可以不用太过关心数据来源是访问数据库、缓存还是来自接口、RPC等,这单纯用模型无法实现。即便是访问数据库,我们也可以将分库和分表条件等逻辑放到仓库层进行处理。

Criteria 我理解为对条件的抽象化。单纯使用模型的时候,很多条件也是重复的,如果被封装便是可被复用的,l5 他们将其直接和请求关联起来,这就简化了很多请求的撰写工作,前端可以直接根据他们标准的查询请求参数直接访问仓库数据。这点上比较 laravel 的 GraphQL 扩展 light-house 已经很接近其强大的查询能力了。

Presenter 我理解为对数据读写的转译,核心还是抽象化。

要不要用仓库模式的问题我的理解是:简单的问题用简单的方法解决。这些设计模式都是在控制项目开发过程中的熵增问题。

4个月前 评论
穿过你的黑发的我的手 (楼主) 4个月前
讨论数量: 5
sanders

平时没有用过,但谈一点我对仓库层的理解。

第一点是做数据访问的进一步抽象化,这方面可以考虑一个场景:

业务通过仓库获取数据的时候,可以不用太过关心数据来源是访问数据库、缓存还是来自接口、RPC等,这单纯用模型无法实现。即便是访问数据库,我们也可以将分库和分表条件等逻辑放到仓库层进行处理。

Criteria 我理解为对条件的抽象化。单纯使用模型的时候,很多条件也是重复的,如果被封装便是可被复用的,l5 他们将其直接和请求关联起来,这就简化了很多请求的撰写工作,前端可以直接根据他们标准的查询请求参数直接访问仓库数据。这点上比较 laravel 的 GraphQL 扩展 light-house 已经很接近其强大的查询能力了。

Presenter 我理解为对数据读写的转译,核心还是抽象化。

要不要用仓库模式的问题我的理解是:简单的问题用简单的方法解决。这些设计模式都是在控制项目开发过程中的熵增问题。

4个月前 评论
穿过你的黑发的我的手 (楼主) 4个月前

只用过 Repository,说说我的理解,不确定够不够准确。场景是后台一套 API, 小程序一套 API,web 前台使用 blade 模板。 三端获取文章列表有一些共用的约束条件,如果直接使用 Eloquent ,将来如有修改需要改三个地方,一来比较麻烦,二来可能会忘了改动某处。三端共用一个 Repository 后,一来修改省事,二来能保持一致性。

4个月前 评论
梦想星辰大海

大佬曾经说过:“Algorithms + Data Structures = Programs”。

作为crud的业务仔的我,是这样理解的:存取数据(dao)+业务逻辑(service)=程序。

3个月前 评论
panda-sir

其实这些都是抽象 都是基于项目设计的抽象 比如你要做一个用户管理的模块 包括用户的增删改查等操作 但你先不写实现 先抛开实现写抽象 抽象不依赖任何东西 只要定义好输入和输出 符合你的需求就可以了
然后你再考虑对抽象的实现 比如你们现在数据是基于Mysql的存储 那你就可以写一个对这个抽象类mysql版的实现 如果哪天你们换实现了, 可能觉得mysql太慢了换redis或者直接接第三方了, 你就可以对这个抽象类写一个另外的实现 简单来说 抽象不依赖于实现 业务不改变的情况下 抽象的实现类是可以多种多样并且快速根据具体情况去切换的 业务改变的情况下 也是一样的 先去对抽象类进行修改 然后再修改对应实现类 Repository你也可以这么理解 可能有个UserRepositoryInterface 这个用户仓库抽象类不依赖任何服务 对UserRepositoryInterface的实现类才会在实例化的时候注入对应的依赖服务

3个月前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!