graphql 多个graphqls文件_如何用GraphQL+JavaPoet把前端逼成瓶颈

本文探讨了如何将GraphQL Schema转换为Dgraphql Schema,并利用JavaPoet生成Java代码,以此提高开发效率。文章详细介绍了从解析GraphQL Schema到生成Java接口的过程,以及在实施过程中遇到的问题和解决方案,包括缺陷分析,如GraphQL描述能力的局限性,代码生成与实现的混合问题等。
摘要由CSDN通过智能技术生成

上篇文章《DDD探险——基于GraphQL+Dgraph实践》中提到了一种假设

如果前端能通过领域模型进行数据操作,能否通过GraphQL Schema同时描述领域模型、API接口以及数据库结构?

基于此假设提供了Arc框架,同时采用Dgraph作为数据存储。
既然我们已经有了Schema,能否基于这个描述自动生成系统实现?通过降低开发成本、提升效率,继而达成快速迭代、试错领域模型的目的。

尝试通过代码生成器来完成这个假设。

1. GraphQL Schema -> Dgraphql Schema

1.1 概念:

  1. Dgraph Schema: Dgraph数据库结构化语句,类似mysql中的DDL

  2. predicate: Dgraph的数据库字段,一个predicate可以被多个type使用

  3. domainClass: Arc框架中定义javaBean类型,用于反序列化

1.2 方案

解析GraphQL Schema后,根据转换逻辑生成Dgraph Schema

b25e4da2de85fc09eff5fbc2f09f9bb9.png

注意Arc框架限制

  1. DB结构中拥有框架依赖通用predicate,如 domainClass

  2. 为了解决predicate跨type定义问题,dgraph中的predicate命名增加type为前缀

1.3 注意

  1. 需要框架提供根据Dgraph Schema自动初始化数据库的能力

2. GraphQL Schema -> JavaCode

2.1 JavaPoet

JavaPoet is a Java API for generating .java source files.

通过JavaPoet可以方便、详细的描述Java源文件并生成。

看官方issue发现很多人希望提供快速生成getter、setter方法的方式,官方并未采纳,给出的回复是

Basically we're a tool for generating exactly what you tell us and not a tool for inferring code to generate. You can write a static method or helper class which can produce a field, getter, and setting in one shot onto a TypeSpec.Builder.

这个回复也明确了JavaPoet的定位。其实生成相关方法的方式非常简单

522418ec67d38ede4ad256ab5720ce03.png

提供一个生成Builder的示例,基本涵盖了全部定义

ebcd8530e7a4d6380521404c104cc9ce.png

2.2 实现

基于 graphql-java 解析 Graphql Schema,通过 javapoet 按照Arc约束生成相关java文件

  • Graphql Enum -> dictionary

  • Graphql input -> input

  • Graphql type -> typeapirepository

2.3 注意

  1. 通过只提供interface方式,避免修改生成的代码。保障每次schema变更后都可以重新生成。

  2. 如果存在需要修改生成代码的场景,通过配置方式跳过相关Java源文件生成。

3. Maven Plugin

生成逻辑通过上述定义完成后,如何触发生成的动作?Maven插件是一个不错的选择。 
只需要继承AbstractMojo类并在Override execute()中调用相关生成方法即可。这里暂不展开如何开发Maven插件

b092d8e421abe5e0cdb5e5c90182c9ad.png

然后再命令行执行

mvn arc:generate

即可按照配置及规则生成相关代码。也可以通过参数决定只生成java代码,不生成Dgraph Schema

mvn arc:generate -Dtarget=java

4. 效果

4.1 创建schema. 默认路径为 resources:graphql/schema.graphqls

4.2 新建配置文件, 默认路径为 resources:arc-generator.json

eb88134a80ea3c04f3506e6978d922b4.png

4.3 执行命令行

67c91c5378a2b4310df5183cbe12d702.png 4.4 代码生成

fcffe513116350be5c44e8e05fe4a695.png

在聊清楚schema后,只需要执行一行命令,然后编写一个实现类即可完成接口服务的开发。在schema修改后,重复执行这个过程。

5. 缺陷

5.1 GraphQL描述力不够。只描述来数据结构与类型,没有描述数据存储可能会用到的主键、索引、缓存等信息,以及DDD中的限界上下文(BoundedContext)、聚合根(AggregateRoot)等概念

可以通过自定义directive实现相关扩展定义,比如: 

但是这个时候QL已经变成了DSL,需要考虑额外的学习、推广成本

5.2 生成的代码和实现代码混合,如何进行code review?

schema和生成的代码先提交一次PR,对schema进行review。之后的实现代码再单独提交PR

5.3 Dgraph更新时数据如何处理?

已经上线后无法自动迭代。数据版本迁移不应属于开发过程

5.4 仍需编写实现类(生成的代码是否允许编辑)?

理想情况是完全通过代码生成完成相关实现。但是实际业务并不是简单的crud,如果通过schema描述复杂业务,就会发现本质上是通过schema来编写另一种java代码。所以只生成interface,需要开发者补全相关实现。让schema专注于描述DDD。不排除提供生成简单crud实现的功能,在修改了相关实现类后,再通过配置SKIP_IF_EXISTED跳过相关实现

5.5 自动化生成后发现无事可做,不可替代性如何保障?

-_-#

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值