hi, 我是 pydantic-resolve 作者(也是那篇 composition oriented development pattern 的作者) , 在声明式描述数据这点上我很赞同你的观点, 我观点上的一些分歧在于是否应该和 ORM 关联的紧密,下面是我的解释。
首先,既然用申明方式来生成数据, 目的肯定是为了更加优雅的组合数据
一般来说, 后端生成一个前端直接可用的视图数据包括几个步骤。
1. 数据获取
2. 数据组装 (utilmeta 把 1 ,2 两个环节一次性解决了)
3. 面向业务进行转换 这么几个步骤。
(一般情况下 2 ,3 可能会混在一起)
我选择使用 dataloader 的原因是:
通过 ORM 获取关联数据的手段之一,这个行为如果用通用的描述来说的话, 类似于:
def batch_query(keys, filters) 然后把查询结果绑定回每一条父记录。
这样在一对多查找的时候,既能使用外键, 还能指定额外过滤条件
https://github.com/allmonday/composition-oriented-development-pattern/blob/master/src/router/sample_2/readme-cn.md( ORM relationship 上添加额外条件的查询写起来通常都会比较繁杂)
也就是说,loader 的内部实现可能是一段查询, 也可能是一个 rpc , 也可能是缓存查询 等等
这样做的好处是隔离了具体实现, 假如我要做服务拆分的话, 就能将封装的查询,转成一个 rpc 调用了。
关于 3 , 数据转换, 这也是直接从 ORM 拼装数据可能存在的一个小问题, 如果视图数据需要对视图数据的中间, 或者底层的数据做些转换, 聚合计算之类的功能, 很多时候就不得不拆开来遍历计算了。
pydantic-resolve 的思路是选择使用 post_method 来在每层提供一个 after resolved hook 来操作数据。 用来处理层级聚合, 字段转换会比较方便, 也符合声明式的风格。
https://github.com/allmonday/composition-oriented-development-pattern/blob/master/src/router/sample_4/readme-cn.md说了一些拙见,框架本身是服务于特定目的,
utilmeta 这样的申明式方法带来了很好的灵活性和使用便利。
而且被你详细的文档和丰富的 example 给震撼到了!
祝蒸蒸日上