V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX  ›  kkhaike  ›  全部回复第 7 页 / 共 35 页
回复总数  699
1 ... 3  4  5  6  7  8  9  10  11  12 ... 35  
2022-08-07 12:01:59 +08:00
回复了 a132811 创建的主题 Go 编程语言 感觉 uber/fx 并不比 getInstance 工厂好用
关于黑盒测试
1. 上面我也补充了,不需要放在顶层,放在你待测 Provide 目录中就行就行,你可能没看到吧。。在 16 层
2. 私有函数问题,你可以试着封装 2 个 interface
M interface -> 外部暴露函数
P interface -> 黑盒测试私有函数
你的 module 对象是实现 M + P, New 只提供 M
这样的话 你在 Populate 出 M 的时候,可以通过 m.(P) 转成泥似的私有 interface 进行调用。
3. 不需要的模块,以及需要切换成 mock 的模块,我在上面说了可以通过 Replace 替换掉

总之,总体目标就是不要为每一个 Provide 间 测试构造你的依赖,问题总有解决方法

关于生成
1. 我的生成框架是识别 New 函数上的 @dep 注解,
然后在 app 包里添加对应的 Provide ,以及生成对应的 dep 参数对象,
是为了解决你说的维护 Provide 问题,整个框架只需要修改 @dep 注解就好。
2022-08-04 20:40:21 +08:00
回复了 jeesk 创建的主题 Go 编程语言 第三方的 errors 包是不是没有人用了?
直接用 google 的 xerrors 吧 其他的应该都淘汰了
2022-08-04 19:40:07 +08:00
回复了 a132811 创建的主题 Go 编程语言 感觉 uber/fx 并不比 getInstance 工厂好用
fx 的初始化逻辑简单概括就是
1. 初始化所有 fx.Invoke 的所有依赖
2. 顺执行 fx.Invoke

所以 fx 最佳实践就是用一个包管理所有依赖,因为他会按需创建

我上面的 Provide 间 UT 例子,他就只会创建你 Populate 对象所有依赖

另外。。。我的 app 模块甚至都是 go generate 生成的。。
甚至,上面我举例的 dep 依赖结构都是生成的。。

我模块代码只有
```

type M = *module

type module struct {
*dep
}

//go:generate bb gen $GOFILE
// @dep(dao)
func New(d dep) (_ M, err error) {
}
```
2022-08-04 19:31:47 +08:00
回复了 a132811 创建的主题 Go 编程语言 感觉 uber/fx 并不比 getInstance 工厂好用
另外我上面说的黑盒测试补充一下。。。
由于 go 循环引用的原因,一般黑盒测试是定义在被测包同层文件目录中,
包名是 xxx_test ,

比如 xxx 目录为 package xxx ,他下面有
xxx.go 包名是 xxx
xxx_test.go 白盒,包名是 xxx
xxx_bb_test.go 黑盒,包名是 xxx_test
2022-08-04 19:26:30 +08:00
回复了 a132811 创建的主题 Go 编程语言 感觉 uber/fx 并不比 getInstance 工厂好用
另外我在说说 fx. Lifecycle ,这个东西是你 getInstance 怎么都做不到的。
想象一下一个几十个 Provide 瞬间无措优雅关停的快感。。

什么,你们你们不优雅关停。。那么当我多说了
2022-08-04 19:15:51 +08:00
回复了 a132811 创建的主题 Go 编程语言 感觉 uber/fx 并不比 getInstance 工厂好用
我使用 fx 大概两年左右,下面就针对楼主各点给出我的看法。。

PS1. 新出的 fx.Module 还没想到用得到地方,可能我项目不够大吧。

# 手动维护依赖属性
使用 fx.In 参数对象解决依赖问题,我一般一个依赖一个包,所以都是这样写的 New 护士

```
// dep 专门用来给 fx 注入参数
type dep struct {
fx.in

dao dao.M // 为了单测方便,数据层的一般都提供 interface
busi busi.M
}

// 这里看这个模块的情况,想被 mock 就写
// type M interface {
// bala()
// }
type M = *module

type module struct {
*dep // 内嵌指针就好了

some int // 内部变量
}

// 私有参数,让其无法手动调用,只用来 fx
func New(d dep) M {
return &module(dep: &dep)
}

```

server->service->db Provide 定义问题,因为我每个 Provide 都分包的,
所以要增加一个 fx.Invoke 去注册 service 到 server

所以,Server 是单独 New 出 Provide 的,无依赖(他被人依赖)
所以就有三个 fx.Provide
1. dao.New 无依赖
2. service.New 依赖 dao
3. server.New 无依赖
两个 fx.Invoke
4. service.Reg 依赖 server, service ,实现 server.Reg(service)
2. server.Life 注册 server 启停,注意最好用 fx.Lifecycle 注册,不要直接调用

如果嫌弃一个 service 定义两个 Option 很麻烦的话,
实际上,service.M 基本不会被其他 Provide 使用,所以也可以省略 service.New ,
直接在 service.Reg 中完成,New 和 绑定操作

可以看出。实际上加属性,也只需要修改一个地方,即 dep 成员,整个也很简单

# 写单元测试有点麻烦
与楼主相反,我觉得倒是写 UT 非常简单。。

由于我按每个 Provide 分包,所以 UT 分为 Provide 内 UT ,Provide 间 UT

Provide 内 UT ,直接 new 对象,按需初始化成员就好了,不要走 New 函数创建对象,
因为 和其他的 Provide 内 无关,所以 UT 根本不需要 fx 介入,比如我上面依赖 dao.M 的例子
可以直接创建该成员 mock 对象

Provide 间 UT ,由于 fx 的特殊原因,以及 go 的循环引用问题,所以 Provide 间 UT 只能用在
黑盒测试,我是这么处理的

有一个 app 模块 管理所有 Provide/Invoke ,main 直接调用 app.App().Start() 启动程序

```
func TestXXX(t *testing.T) {
var m some.M
defer fxtest.New(t, app.Provides(), fx.Populate(&m)).RequireStart().RequireStop()
}
```

你还可以用新出的 fx.Replace 替换链上的依赖为 mock

# 其他点
5. 性能损失:fx 只作用于你程序的初始化阶段。。。这个阶段谈性能损失?
6. 调试、维护略复杂,你可能是没用 fx.Logger ,我用了 2 年都没有调试过 fx
2022-07-23 18:01:22 +08:00
回复了 vlitter 创建的主题 Google 悲剧了, google voice 号被收回了,哪位大哥帮忙验证一下
我也被收回了,有啥办法拿回
2022-07-11 10:16:48 +08:00
回复了 revalue 创建的主题 macOS 想换电脑了,旧 macbook 怎么伪装成坏掉的样子
小锤 40
2022-06-05 15:12:46 +08:00
回复了 KanadeCCCC 创建的主题 Apple 说说看大家心目中的 iPad /iPadOS
其实 IpadOS 增加个 HyperV 不知道生产力高多少
2022-06-02 13:57:29 +08:00
回复了 liuchenx 创建的主题 机械键盘 ikbc 这品控不行啊
我也是 ikbc 的,这家伙蓝牙经常卡。但是接 m1 的蓝牙又会好一点。。接 2018 款 就不行
2022-06-01 18:01:47 +08:00
回复了 xxjwxc 创建的主题 Go 编程语言 golang 实现的一套 A 股量化系统
研究大 A 不如研究美股
2022-05-05 12:41:11 +08:00
回复了 shawnliu03 创建的主题 iDev 业余玩家如果进行 iOS 开发
@shawnliu03 完全辅导解惑性质也行
2022-05-04 18:22:53 +08:00
回复了 shawnliu03 创建的主题 iDev 业余玩家如果进行 iOS 开发
@shawnliu03 要不一起合作。我也有几年没写了。想重新熟悉下。wx: a2toYWlrZQ==
2022-04-23 17:23:41 +08:00
回复了 tlmn 创建的主题 Go 编程语言 golang 有什么好用的命令行解析实现库么
2022-04-23 17:22:52 +08:00
回复了 tlmn 创建的主题 Go 编程语言 golang 有什么好用的命令行解析实现库么
2022-04-23 09:17:52 +08:00
回复了 WintersZhang 创建的主题 Go 编程语言 有 go 的多功能工具库推荐吗
2022-04-23 09:12:34 +08:00
回复了 tlmn 创建的主题 Go 编程语言 golang 有什么好用的命令行解析实现库么
我的项目一般都用
github.com/urfave/cli/v2
2022-03-15 10:49:40 +08:00
回复了 kkhaike 创建的主题 问与答 哪里能找到有偿靠谱的日文脚本翻译
@hakufuasano 现在万字大概多少钱
2022-03-14 21:09:34 +08:00
回复了 kcojkcnw 创建的主题 酷工作 [上海/北京] 小红书/ Java /30-50k ✖️ 15
上海的办公区在哪
1 ... 3  4  5  6  7  8  9  10  11  12 ... 35  
关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   1344 人在线   最高记录 6543   ·     Select Language
创意工作者们的社区
World is powered by solitude
VERSION: 3.9.8.5 · 33ms · UTC 23:59 · PVG 07:59 · LAX 16:59 · JFK 19:59
Developed with CodeLauncher
♥ Do have faith in what you're doing.