V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX  ›  a132811  ›  全部回复第 6 页 / 共 19 页
回复总数  377
1 ... 2  3  4  5  6  7  8  9  10  11 ... 19  
2022-09-05 00:15:29 +08:00
回复了 RedBeanIce 创建的主题 Java [mysql 字段] not null 还是 null default
@GTim 你们做国际化时,传时间都不带时区吗?我们都统一用 rfc3339 表示
现在城市的教育资源还是很紧张的,要么去城市搞教育,要么提前享受养老生活吧。
不过,未来可能不用担心教育、医疗、住房资源不够了
2022-09-04 23:11:08 +08:00
回复了 qingjiaowochangd 创建的主题 问与答 国内有投资了新加坡市场的基金么
其实我倒想知道有没有印度 ETF 的基金
amvim+1 更丝滑,与 vscode 结合得更好,插件代码实现也更轻量级

@SiLenceControL 使用 vim 十多年,也写过 vim 插件。大多数情况速度上相差无几,处理大文件 vim/vscode 都慢。
遇到一些 bug 插件,无论是你是 vim/emacs 还是 vscode/idea ,就是耶稣来了都得跪
2022-08-15 15:06:09 +08:00
回复了 allAboutDbmss 创建的主题 问与答 第一次见大客户 有无礼物推荐?
男士 香水
2022-08-13 17:58:46 +08:00
回复了 ericgui 创建的主题 程序员 日本程序员薪资
@whywaoxaks 小杠一下,在帝都、魔都,多少钱能结婚?
量力而行,如果非要买房,可以考虑你们县城的二手老房,有装修的,成本小。

你最好问自己几个问题,尽量让自己理智一点,买房未必能缓解你的焦虑,观念打开:
1.早上车,怕以后买不起,继续等也没意思,父母无法工作,一个人赚钱存钱慢。等钱存够了,还不知道买不买得起。
房价暴涨的时代大概率是过去了。怕不怕以后房子跌?能否承受失业风险?

2.为婚房提前做准备,早买晚买总要买。
不考虑两人共同奋斗吗?准备贷款多少呢,自己是否能承受失业的压力吗?

3.虽然罹患心理疾病,但是前端开发月供 4k 应该还能接受吧
完全看你的消费支出,自己觉得能承受就行,除了房贷+房租+日常开销,还要留一点谈恋爱的钱、生病的钱、学习和业余爱好的钱

4.自身欲望大,心比天高,命比纸薄
做任何事,做最坏的打算,当期望无法到达时,不要自暴自弃

5.买房后入住想在附近软件园工作,节省房租,幸福感增强。
有时计划赶不上变化,做好自己的风险计划
2022-08-12 19:57:56 +08:00
回复了 x97bgt 创建的主题 程序员 惊魂一刻,密码管理软件的主密码忘记
@guazila 万一钱包掉了或者烧了,就..
2022-08-09 22:58:38 +08:00
回复了 gowk 创建的主题 Go 编程语言 用 Go 写 Web 后端合适吗?
我们组的后端基本是 go ,比 python 好维护太多了,比 java 代码少且好读

不用太担心泛型不够用、重复的代码、性能不够、生态,uber 和字节都大规模的使用,反正造轮子、看第三方包源码都很方便。

现在基本不用自己造轮子了,先看看这里 https://github.com/avelino/awesome-go

我最喜欢的,松散的 package/struct method 等设计,重构代码、组合代码、测试代码都太方便了,几乎是一行流、一键完成,修改调整文件名都不需要重构代码本身
2022-08-09 22:20:55 +08:00
回复了 a132811 创建的主题 Go 编程语言 感觉 uber/fx 并不比 getInstance 工厂好用
抱歉,你说的让我有点疑惑。

>> 1. 上面我也补充了,不需要放在顶层,放在你待测 Provide 目录中就行就行,你可能没看到吧。。在 16 层
在 16 层,你说的是避免循环引用吧?

拿你说的同层目录吧,model/{user.go,user_test.go} 都是放在 model 这个目录。
不还是需要在 model/user_test.go 中创建新的 fx.New(Provide) 吗?怎么能避免创建 fx.New(Provide)呢?

>>2. 私有函数问题,你可以试着封装 2 个 interface 。
>>M interface -> 外部暴露函数
>>P interface -> 黑盒测试私有函数

不太明白你说的黑盒测试私有函数是指什么?

既然是私有函数、方法,那它就不可以暴露给外部(如果能暴露给外部,那它就不应该是私有的)

既然是黑盒测试,那应该是从包的外部访问。既然从外部访问,那只能访问公有函数,而无法访问私有函数吧。

除非,你在内部写一个方法,将私有函数暴露出去(这就属于公有函数了)。

其实我并没有必要外部暴露它呀,如果我想运行这个私有函数,我只需要在同层目录放个 xxx_test.go 就可以访问运行它呀,多简单不是。
-------------
或许,我理解错了,你是指的别的吗?
2022-08-07 00:32:10 +08:00
回复了 Tyaqing 创建的主题 分享创造 国内 pwa“应用商店”能不能做起来呢
我用的 pwa 主要是 squoosh

如果有 pwa 我肯定优先装 pwa (或者纯网页),而不是要安装扫你文件的、臃肿的 APP (淘宝、闲鱼、飞猪、美团、饿了么、甚至 12306 app 我都不想安装的)

关键是要么没有、要么 pwa 功能残缺——不支持微信登录、不能用 google 的 web notification 、IOS 也对 PWA 支持不好。

我本来想写一款支持 markdown 写笔记的 pwa ,不过没有时间去折腾
@a132811 主要缺点是国内不能使用 google 的 Web Notifications
@maomaomao001 挖个坟,chrome pwa 已经开放了文件系统、摄像等主要 API 了。参考:
1. https://fugu-tracker.web.app/#shipped
2. https://whatpwacando.today/

文件系统需要用户授权访问指定的目录。

现在的授权机制已经在安全、易用性、开发效率之间做到很好的平衡了。

Proj fugu 有人提过 fetch without CORS ,但是我是不希望取消跨域 CORS 的,这对网站的数据保护绝对不是好事。

CORS 是各网站本身的要求,如果能轻松绕过 CORS ,随便不小心点一个钓鱼网站就能偷偷爬数据,PWA 应该会受各大网站所反对、更别提国内的审查备案了。

本来 Android App 滥用文件权限,就已经受够了。


想绕过 CORS ,必须要付出点成本:参考 Proj Fugu 提的 feature https://bugs.chromium.org/p/chromium/issues/detail?id=962321
1. 自己部署 cors.your.com 或者使用别人的 cors 代理
2. 或者利用 cors chrome 扩展,扩展这个东西谷歌还是会审查一下的
3. 或者让用户下载一个 app 专门,不干别的事,就提供 CORS 代理,证书什么的让用户自签名(反正是用户自己授权安装的,风险自担)
2022-08-06 17:27:25 +08:00
回复了 a132811 创建的主题 Go 编程语言 感觉 uber/fx 并不比 getInstance 工厂好用
@kkhaike 感谢你的回复。

你给的 fx 用例—— 说明了 fx 能提供很方便的自动依赖注入、lifecycle 、按需创建等等(用 fx.Module 还可以进一步实现对复杂依赖的模块化管理)

但是回避了我说的问题(这取决于你是否这认为这些是问题,如果你认为这些问题可以忽略,那么 fx 自然是很好用; 而我认为这些问题较为重要,大多数情况可通过构造工厂避免,并且不降低项目的可维护性)

我描述的场景,都属于白盒,需要从内部进行,而不是在外围顶层运行:
`fxtest.New(t, app.Provides(), fx.Populate(&m)).RequireStart().RequireStop()`


1. 手动维护依赖属性的场景
>> 可以看出。实际上加属性,也只需要修改一个地方,即 dep 成员,整个也很简单"
你描述的用法属于单个 fx.New 的场景,只需要维护一份依赖关系就行了。

但是我的场景是:**由于要测试、临时运行局部函数**, 此时就需要创建很多不同的 fx.New

**为什么不能避免重新创建 fx.New 呢?**
因为要运行的是局部代码,我想把测试本身也放在局部,局部代码的依赖关系也不一样。所以就不能复用入口层 main.go 中的 fx.New()

fx.In/Out/module 确实能方便的组织依赖关系,但是手动管理 provides 是不能省掉的,用工厂就省掉这一步的。


2. **不完美**的按需创建
fx 虽然提供了注入时才自动创建,但是不能做到 **更完美**的按需创建。

比如,我们使用 fx 为 Service 注入依赖 DB, 创建 Service 时 fx 会自动创建并注入 DB 对象,即使不会真正使用到 DB 对象.

为什么明明依赖了 db 对象,却又不使用它呢?

因为我只是想调试一下单个的方法 Service.FetchApi() ,它并不需要 db 对象,却必须初始化不相关各种 db 对象(有的 db 连接还限制频率、连接失败的问题)

当然了,可以 mock db 嘛,但是有几个问题:只能在注入前 mock 而不能注入后再 mock; 有些 library 并没有暴露私有属性的 mock 方法; 有些复杂的库自身也没有 mock 的能力,比如 uber cadence 并没有 mock-cadene-client 这种东西。

真实的情况,需要 mock 的东西可能会很复杂,如果去研究怎么 mock 就很浪费时间。

3. 单元测试有点麻烦
你提到的
>> 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()
>> }

你这份代码,是在外围顶层 main.go 中建了一份`fxtest.New` 然后 start 运行测试代码。
缺点是:1. 无法测试的局部代码的私有方法 2.需要手动维护测试所需的`app.Provides()`, 3. 外部的 invoke 与内部的被测代码是分离的,所以必须先把被测代码 import 出来。4. 我更喜欢`model/{user.go, user_test.go}` 测试与代码放到一起,并且不需要在外围引入`fxtest.New().Start()`.

我得重复一下问题——fx 确实能避免手动 New ,但是不能避免**手动管理**依赖关系.

我在本文描述中提到的单测 case 就是这样的,简单的说就是:

第一,要手写不同测试所需的不同的 provide ,第二, 要定义一些私有属性来存放注入的对象(复杂测试也需要有专属的依赖注入)

依赖越多,手动写的工作量就就越多.

在 go 下,这种情况把 OOP 换成函数式,此类手动管理的代码,可不需要写,会更简单

4. Lifecycle
一般情况我对 lifecycle 没有特别高要求,需要关停的就那么几个,平滑退出可直接在入口层统一处理

//main.go
func main(){
.....
defer close()
<-ctx.Done()
}
func close(){
if PgFactory.Exists(): PgFactory.Close()
....
EsFactory.Close()
KafkaFactory.Close()
closeHttpServer()
....
}

也可以自定义 context, 把所有要释放的方法注入到全局的 ctx, 然后用 cancel 或者 ctx.Cancel()触发释放


// main.go
serverCtx, cancel := WithCancelFns(context.Background())
....
defer cancel()

// service.go
getServerCtx().AddCancelFns(
func() { println("close pg") },
func() { println("close server") },
)

5. go generate 生成的
>> app 模块甚至都是 go generate 生成的
并不清楚你的 app 是什么实现。
我的经验是 fxTest 初始化的样板代码,我可以用 ide/vscode 的 snippet 一键一生成,只是不同的依赖管理+属性的初始化,不能抽象为模板,还是要手写

6. 循环引用
之所提这个问题,只是为了回应前一位 v 友——循环问题只跟代码结构设计有关,跟 fx 本身无关
> ps, v 站不支持回复加 markdown 缩进全被吃了:)

7. 性能损失
赞同你说的, 确实不关紧要

8. fx 调试
正常调用是没有问题,除了特例:

比如依赖 /接口是自动注入的,当我想了解这个接口到底是哪里初始化的,是需要先了解整个项目的依赖关系图的。而单例工厂则是显式的、直观的。(当处理一个不熟悉的复杂项目时,就会有这个感受)
2022-08-04 12:50:15 +08:00
回复了 a132811 创建的主题 Go 编程语言 感觉 uber/fx 并不比 getInstance 工厂好用
@YuuuuuuH 这里其实就是 setUp 函数,初始化了 fx.New/Module/Invoke 。

不过,由于需要的 provide 依赖不同,所以需要写各种 setUp 函数。
@cmdOptionKana
我认为没有工会并不是 996 的根源,那不过是一种形式(其实有些公司是有工会的),主要看你怎么定义工会了。真正伤害了普遍员工利益的话,大家也是可以组织起来的。我记得 15 年某些地方出租车 ba gong 的事。

我不认为 996 的根源我们这两年批判的资本家,欧美日就是反例,之前就有人投过票,字节非常多的人反对取消大小周。

大家想想自己为什么 996 ,为什么不敢离职、裸辞,来一次说走就走的旅行。路是自己走的,工作是自己选的,为什么不敢?到底是什么大山把自己压着?

为什么 996 已经明确是严重违法的的,却几乎没有人站出来?

为什么现代生产效率提高了,活得却更累了、自由时间越来越少了?

为什么教育医疗资源不足同时,却有越来越多的医学生、师范生内卷,甚至毕业就失业?

为什么房价依然很高的同时,房地产行业却不景气?

是不是太魔幻了?
用来看 deno 的源码
2022-08-01 19:42:16 +08:00
回复了 a132811 创建的主题 Vue.js Vue3 下有什么 umijs 的替代品推荐吗?
@liximomo
---------忘记说背景了, 放假了就没关注-------

也并不是 umijs 有多难用。主要我们的 umijs 旧项目,构建越很慢,走 k8s 部署更慢。

很旧没有升级了,过去积累的 warning 非常多了(不全是 umijs 的,还有其它各种包),然后升级 msfu 遇到些困难(k8s 那里部署就有问题,用了 docker 多步构建)。

以前也升级过,升级体验并不太好。

然后看了下 vue3 的 vite+unocss+...,有一点心动。
2022-07-29 20:01:54 +08:00
回复了 a132811 创建的主题 Go 编程语言 感觉 uber/fx 并不比 getInstance 工厂好用
@blless 不是很同意。

如果没有做好代码分层,无论是 fx ,还是 getInstance ,都无法避免循环依赖。

可能和你想的 getInstance 不一样,我说是构造工厂

1. 我所需要的对象都来自于工厂,调用者不必关心工厂怎么初始化的,也不关心工厂如何实现的、更不关心工厂依赖什么
2. 调用者**只关心工作的输入输出**符合接口规范。这跟 fx 是一致的。
3. 如果工厂如果出错了,应该保证返回 err 或者像 fx 那样返回”failed to build xxx“的 panic
4. 不必要的依赖跟 mock 是两个层面的事情吧。如果是不必要的依赖,最好直接不初始化才对

不太理解你说的`getInstance 再 getInstance 循环`是什么情况,循环依赖在编译前就会报错不是吗?

说太多不如上一段实际的代码,拿我们的之前一个项目来说,简化结构如下:

```
app/
settings/
fx.go
config.go
store/
fx.go
cache/
fx.go
redlock/
fx.go
redlock.go
redlock_test.go
pg/
es/
kafka/
....
service/
service1/
service2/
....
main.go
```

虽然引入了 fx, 但是加功能测试`redlock_test`时就发现有循环依赖:
```
$ cat ./store/cache/redlock/redlock_test.go
func TestRedlock(t *testing.T) {
fx.New(
settings.Module,
fx.Provide(xxx),
....
}
$ go test -v ./store/cache/redlock/
package app/store/cached/redlock
imports app/store
imports app/service
imports app/settings: import cycle not allowed in test
FAIL app/store/cache/redlock [setup failed]
```

原因是, 因为 app/settings/fx.go 包含了依赖了各种配置的构造器

```
import (
"app/service"
"app/store/pg"
"app/store/es"
"app/service/..."
...
)


// yaml 文件配置解析
func GetConfig() (config *Config) {
...
}

// 各种配置的构造器
func NewRedisUniversalOptions(config *Config) *redis.UniversalOptions {... }
func NewPostgresOptions(config *Config) *pg.Options {...}
func NewEsOptions(config *Config) *es.Options {...}
func NewService1Options(config *Config) *srv1.Options {...}
....

var Module = fx.Module("settings",
fx.Provide(
GetConfig,
NewRedisUniversalOptions,
NewPgOptions,
NewEsOptions,
NewService1Config,
....
),
)
```

可以看到
1. setting 基础配置,依赖其它种 store(rddis/es/pg/kafka...),甚至 service 的 Options 类
2. setting 是其它库的上层,而不是底层。只有顶层的 main.go 可调用 setting ,其它不行
3. 我们就不能在其它包内引用这个 setting, 想引用的话就需要重新对配置解耦合。

还是那句话,无论是工厂还是 fx ,代码如果没有做好良好的解耦分层,项目都不会那么好维护。
2022-07-27 15:29:39 +08:00
回复了 Ufo666 创建的主题 Java 以后安装一个软件是不是可以直接用 docker 啊
@MengiNo 用-v 映射,就无法自动补全了。除非`-v /data/demo:/data/demo` 保持一致
1 ... 2  3  4  5  6  7  8  9  10  11 ... 19  
关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   3334 人在线   最高记录 6543   ·     Select Language
创意工作者们的社区
World is powered by solitude
VERSION: 3.9.8.5 · 37ms · UTC 11:30 · PVG 19:30 · LAX 04:30 · JFK 07:30
Developed with CodeLauncher
♥ Do have faith in what you're doing.