一、时间安排

2022-04-28 21:00 如遇不可预料的时间冲突,时间另行交流确定。

预计会议时间 30 分钟。

二、会议地址

郭强 邀请您参加腾讯会议
会议主题:GoFrame工程化改进交流:接口化、依赖注入设计
会议时间:2022/04/28 21:00-21:30 (GMT+08:00) 中国标准时间 - 北京

点击链接入会,或添加至会议列表:
https://meeting.tencent.com/dm/VwOiDwqfApbG

#腾讯会议:712-775-838

复制该信息,打开手机腾讯会议即可参与

三、会议内容

本次会议由 郭强 提供主题和一些思考、验证功能分享,对其中的内容大家可以结合现有的行业实现提供合理的建议,共同讨论。

1、工程化中的一些痛点

  • 在工程目录设计中,service层沉淀的业务逻辑越来越多,后期的维护越来越复杂
  • service层单目录下过多的代码文件,小心翼翼组织代码,造成压抑的代码开发体验
  • service无法使用包管理,否则极易出现循环包依赖问题,因此必须采用接口化解耦

2、基础分层仍旧按照职责分层

  • 基础分类按照功能职责,极大规避业务包依赖
  • 例如,controller层作为独立的controller包,可以依赖所有的service业务包,因此在一个请求中可以通过调用不同的业务包方法来实现功能,这也是鼓励的做法
  • 对service层按照业务模块进行包管理。从包设计理论上来讲,一个包应当尽量低耦,这种低耦不仅是代码上的,更是逻辑上的。一个业务包中难以通过依赖过多的其他业务包来实现功能。

3、部分层级仍旧采用单包管理

  • 例如 api/controller/consts/model
  • 这部分层级从工程设计以及长期维护来讲,低复杂度,无需采用包管理
  • 这部分层级的代码采用包管理的成本会高于单包维护成本,这是从务实考虑

4、提高效率的工具命令设计

  • gf gen service
  • 自动根据logic层包代码分析生成service层接口、logic自动引用文件
  • 支持Goland集成,支持编码中自动更新service
  • 接口的实现需要开发者在业务包中手动注入

5、API接口层与gRPC支持的思考

  • 使用api层管理业务的输入输出
  • 不同协议的支持由工程自动生成的代码实现:不需要学习proto语法、也没有中间协议学习负担
  • 对于其他微服务通信协议也同样如此
  • 这样才能实现 开发者只需要关心业务 的目标,一个框架本该就如此

四、视频地址

https://www.bilibili.com/video/BV1m34y1e7MN/



Content Menu

  • No labels

13 Comments

  1. 部分留言:

    1. 生成的Interface 是否考虑 复制 注释信息? 
      • 一个是因为复制和自动同步注释信息较为复杂,投入和收益比不高。
      • 二个是我本人提倡良好的方法名称定义胜于复杂的注释说明,80%方法的注释基本都不需要的。
      • 所以复制注释信息的收益不大,可能不太会做这个事。
    1. servicelogic是接口与实现的关系,目前这样是分离的,建议放到同一个层级下。这样目录会更清晰。
    2. gf gen目前是跟库表对应的,业务逻辑经常会多表组合来实现,难免service会相互调用实现逻辑目标,如果都放controller去调service又会让controller承载太多跟接口无关的业务逻辑。有什么好建议?
    3. dao目录是否还是放service下,保持好的调用规范与习惯呢?企业级团队对项目统一调用方向还挺重要的,降低沟通理解成本。
    1. 1. logic是具体的业务逻辑封装、具体的业务实现。service在后续都只会有接口定义、基本的接口注入和实现获取,目的是将logic中各个业务模块按照接口进行解耦。两者的职责很明确、界限是很清晰的,因此我们刻意将logicservice分离。
      此外,如果业务模块过多,service在后续可能也会比较复杂,如果两者放同一层级的话会比较混乱。
      再者,挺大一部分的场景下,大家只会关心logic实现,并不会关心service的存在,因为service可以由工具完全接管维护,自动代码生成。

      2. 这是开发常见问题,我在昨晚会议中也提到过,在controller聚合多个业务模块结果,或者在logic方法中聚合多个业务模块实现功能两种开发方式都存在。前者在controller中耦合,后者在logic业务模块中耦合。我个人推荐尽量在前者中聚合维护,让各个业务模块尽量低耦。前者的好处是,一旦logic完善后,controller就可以通过不同的logic业务模块搭配来实现不同的api。后者的缺陷是,会造成logic的特定方法只为特定的api服务,耦合较大、难以复用,很难实现前者的好处。同时,一旦与客户端约定的api结构变动,也会影响内部logic功能,这是不太合理的。不过,知易行难,参差不齐的开发者往往很难掌握其中的力道。写代码是门手艺,拿捏得道却是门艺术。

      3. 下个版本,生成的dao/do都可以自定义生成位置。

      1. 关于第二点,认同。但是建议gf gen service 不要强行跟表一一对应进行分包,因为很多内部逻辑是跨多表实现的,例如订单head表与订单detail表。都搬去controller才能进行编写订单逻辑,显然会让controller太重,而service只剩下CURD的功能。建议使用domain业务领域的设计,同一业务领域的逻辑本就应该在同一个包里进行调用。

        1. 哦,你这么说,我在这里有个重点忘了提醒了!

          • service的接口设计和数据表没有任何关系,只跟logic业务逻辑封装对象有关系,多个接口在service下是单包管理方式,可能会存在重名情况(这块代码生成工具会报错提醒)。
          • logic下的包是开发者自己命名的,一般按照业务模块来封装,按照领域模型来设计也是可以的,自由发挥。
  2. 关于代码生成的顺序有个建议:

    1,定义api文件

    2,工具跟据api的定义生成service的接口

    3,再去实现logic的俱体实现。

    这样更符合习惯。

      • 后续有计划可以默认生成业务模块CURD的api/controller/model/logic/service
      • 可以根据api定义去生成controller,但是service是属于内部业务模块通用性的功能定义接口,不应该和外部api耦合的
  3. 请问一下有提供启用多个server的方法吗?没有得话,下面这种方式可行吗?

    func main() {
    go cmd.Api.Run(gctx.New())
    cmd.Admin.Run(gctx.New())
    }
    多应用有没有案例呀,因为逻辑层大部分代码,比如前后台可以通用,拆成两个应用不得再复制粘贴过去。
    1. 可以用server.Start()启动多个 ghttp package - github.com/gogf/gf/v2/net/ghttp - pkg.go.dev

      server.Wait()阻塞

    2. 可以的,有两种方法,一种是多端口监听,参考示例:开始使用

      另外一种是多个Server相同端口监听,通过SetListener实现。

      1. 您好,相同端口监听,使用SetListener如何实现,可以给个demo嘛

  4. 像一些web接口,避免不了会有很多增删改查的操作,怎么去定义一些公共的方法去实现不同数据表的增删改查的调用。