当我们封装Go MVC框架时需要注意什么?

在公司推行Go框架web开发已经很长一段时间了,最近随着业务方越来越多,发现框架设计的部分不合理性,下面简单说明。

现状

该框架支持Http、Grpc、Cron三种模式。定位是服务于业务开发同学,引入后可以满足各类开发需要,因此我们提供了完备的埋点追踪,客户端(Mysql/Redis/HttpClient…)封装,以确保全公司的Go开发规范标准统一。

该框架非常稳定,仅提供业务无关的MVC开发能力,随着时间推移已经很少更新,趋于稳定。

随着业务对接的越来越多,发现不同的业务往往需要使用一些公共的功能,比如字符串处理、时间处理、第三方SDK等等,它们显然不适合写到稳定的MVC框架中,而应该独立一些公共仓库来实现模块共享。

我们建立了业务侧的公共仓库,并制定了贡献代码的规范,随着越来越多业务同学开始贡献业务侧公共库,一个问题开始显现。

问题

我们假设公共库封装了一些第三方的SDK,那么这些SDK都需要调用HTTP接口,我们希望公共库可以使用MVC框架中的HttpClient,因为我们在内部支持了APM埋点特性,并且其API设计非常易于使用。

然而,因为我们将所有的客户端封装直接放在了MVC框架仓库中,导致这些SDK必须反向依赖MVC框架仓库。

项目理论上会同时引入MVC框架以及业务侧的lib。

然而lib仅仅为了使用Http/Mysql/Redis等封装客户端,却要依赖完整的MVC框架,这个虚线关系是不合理的。

改变设计

显然,zdm-go框架中的所有客户端封装应该下沉,让zdm-go-lib和zdm-go共同依赖:

经过进一步设计泛化,我们让zdm-go仅实现服务接入与MVC分层的相关逻辑,其他基础库全部下沉到zdm-go-base。

经过解耦后,zdm-go与zdm-go-lib仅仅是zdm-go-base的需求方,因此下沉基础库的能力可以被更多其他仓库复用。

PS:一个正常使用场景是,go-app初始化zdm-go框架,zdm-go框架初始化zdm-go-base,那么go-app通过zdm-go-lib可以直接使用已经初始化好的zdm-go-base(比如里面的Mysql/Http等客户端)。

总结

框架设计依赖架构师的经验,确保API清晰稳定,确保组织关系易于扩展。

如果文章帮助您解决了工作难题,您可以帮我点击屏幕上的任意广告,或者赞助少量费用来支持我的持续创作,谢谢~