一次 GO 项目重构的疑问

257 天前
 yujianwjj
type A struct {
   a ComponentA
   b ComponentB
   d ComponentD
}
func NewA(a ComponentA, b ComponentB, d ComponentD) {}
type B struct {
   b ComponentB
   c ComponentC
   d ComponentD
}
func NewB(b ComponentB, c ComponentC, d ComponentD) {}


// 大概有十几个这样的 struct
....

这十几个 struct 都有一些共同的变量(当然也不是完全一模一样)。 现在是每个结构体的 New 方法传的参数都不一样。当然这十几个 struct 其实做的功能比较相似(每个 struct 其实是 k8s 里面 crd 的 controller ),代码结构也有一定的相似性。

现在重构后的代码

type Common struct {
   a ComponentA
   b ComponentB
   c ComponentC
   d ComponentD
   // 一共大概 20 几个
   ...
}

type A struct {
    *Common
}
type B struct {
    *Common
}

这样重构后,每个结构体的 New 方法的参数就很简单,只要传一个 Common 就好了。 但是,这样每个结构体其实引入了一些自己不需要的东西,我自己感觉不是特别好。

各位大佬怎么看?

3348 次点击
所在节点    Go 编程语言
21 条回复
NessajCN
257 天前
别 func New 了,go 里直接就能 newA := A{a,b,c}
zzhaolei
257 天前
用 wire 或者 fx 做依赖注入
vczyh
257 天前
struct 你要有实际意义,common 这种模糊的东西最好去掉,看似提出公共东西了,但是一点也不好维护,不同的东西就是应该分成多个 struct ,要是你觉得一样那就重新思考到底是不是不同的东西,如果是那就分开好了,成员变量相似又不是相同。
vczyh
257 天前
@NessajCN 你没想过变量的可访问性?
Reficul
257 天前
感觉还不如之前的,你要是嫌麻烦可以用 Wire 这样的 DI 工具。
jrqlxue
257 天前
从写代码的角度,我肯定更喜欢一个 Common 搞定。
以及更激进些,ComponentA ComponentB ComponentC ComponentD 是否能合并成 Component 呢😁
8355
257 天前
习惯开发弱类型语言脚本语言的老毛病了
现在这种重构之后实际会更难维护,更容易出现问题
代码量的多少不等于性能的快慢
xinyu391
257 天前
@vczyh 他这里 common 相当于一个 Component 的集合,相当于一个 List 容器。
我倒是觉得 重构后的结构倒是可以的。
zzfly256
257 天前
感觉不如之前的直观,心智负担稍微增加;同建议用 Wire 类的工具
BeautifulSoap
257 天前
用 wire 或 dig 这种 di 库
pkoukk
257 天前
同上,不建议做这种改造,可以用 DI 工具
fregie
257 天前
这光看代码结构没有意义啊,要看这些 struct 实际的含义,是在业务上否能抽象出一个共同的概念出来,如果是完全不一样的东西只是长得像,还非要合并就是画蛇添足
mightybruce
257 天前
你这个设计 完全可以考虑使用 DI,从目前的代码上看,这种重构并没有什么好转,关键看业务逻辑和非业务逻辑有没有分开。
NewA NewB 这种写法说实话很差, 考虑一下 builder 模式 和 option 模式吧。
vczyh
257 天前
@xinyu391
每个结构引入了一些不需要的东西

看怎么理解了
dacapoday
257 天前
画蛇添足
dacapoday
257 天前
面向业务的项目,不要有任何的 common, util, core, helper, global config 。逻辑相似不代表可以复用,过多使用宽泛的命名和结构只会导致耦合。
gitrebase
257 天前
@dacapoday #18 赞同,尤其是所谓的 common 和 global config ,在未来一定会被骂的
sampeng
256 天前
你是反着来重构的,我上一版代码就是你想弄个 Common 的模式,我叫 GlobalService 。后来仔细琢磨了一下,这玩意就是写时一时爽,维护火葬场。一般项目维护时间是要大于写代码时间的。写代码稍微啰嗦点其实也没啥。所以用 wire 来解决写 New 的啰嗦问题。然后代码就清晰很多了。明确知道依赖是怎么进来的,怎么初始化的。

只有一些像 db 啊之类中间件的句柄我就直接整了个 GlobalComponent 。这种我个人仔细思考了是无所谓的。中间件这东西选好了基本就不会动,最多动选型。依赖的是接口。后续也好调整。
houshuu
256 天前
虽然写 Go 不太做 DI ,但这情况倒是明显是挺适合的,我们组一直用的 https://github.com/uber-go/dig
Nazz
256 天前
考虑下全局变量?

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1020966

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX