-
Notifications
You must be signed in to change notification settings - Fork 26
Refactor 重构网络类 #147
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Refactor 重构网络类 #147
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
这次 PR 主要做了一次 Microsoft 账户认证相关的网络层重构,移除了大量旧的 Result 泛型包装和 Net 工具类,用了新的 NetService/StaticNet,并加了一套 HttpClient 池,各种接口签名也都直接返回异常了,代码风格有明显改变。整体来说,重构思路没问题,接口简洁了不少,网络层抽象也更加清晰,但细节上还是有不少地方值得推敲和改进。我细看了一下所有改动,下面我就像个老工程师一样(比较唠叨的那种)),絮絮叨叨地把发现的问题给你捋一遍。
首先,NetService 和 StaticNet 的设计思路是对的,但你们的 HttpClient 池实现其实没太大必要,这里管理 HttpClient 的生命周期反而容易引发资源泄漏和并发问题。比如 HttpClientPool 里用 Timer 定时清理,InUse 标记,实际并没有保证线程安全,Dispose 也只是简单地设置 InUse=false,没有真正释放资源。建议如果没有特殊需求,可以直接用 DI 生命周期托管 HttpClient,或者用 IHttpClientFactory,这样就不用自己造轮子了。自己管理 HttpClient 容易踩坑,尤其是池里一旦有异常或并发场景,Timer 清理不及时,容易造成连接泄漏。
其次,异常的处理方式变了,Result 包装全都去掉,直接用异常传播。这看起来更 .NET 风格,但后续业务调用方必须写 try-catch,不然异常直接冒到上层,整个流程会中断,体验不太友好。比如 AccountService 里 RefreshMicrosoftAccountAsync,现在 catch 的粒度很粗,只有最外层,内部 MicrosoftAuthService 的所有网络异常都直接抛出来了。建议还是能在底层做一层异常包裹,或者加个错误码、错误对象,这样调用方能更细致地判断错误类型,比如网络错误、认证失败、token 过期等等,否则只能靠异常类型去分辨,业务逻辑不好展开。
DeviceFlow 相关的 State 类也有变化,原来是普通 class,现在直接继承 Exception。这个做法不太妥当,业务状态和异常最好分开,DeviceFlowDeclined、Expired 等本质上是认证流程状态,不应该用 Exception 表达。建议还是保持原来的 State 类型,异常只用来表示真正的错误,而不是流程分支,否则未来流程判断时,只能靠 try-catch,代码可读性和维护性都下降。
接口签名统一了,IMicrosoftAuthService 几乎所有方法都去掉了泛型 Result 包装,直接返回业务对象或抛异常。这个没错,但 Result 类其实有用,比如 PollForTokenAsync 轮询时,各种状态码(declined、expired、pending 等)直接用异常抛出,调用方只能靠 catch 来分辨,失去了原来 Result.Error 的细粒度处理能力,而且如果后续要支持更多状态(比如为未来的 OAuth 扩展),会很难扩展。
网络层的 StaticNet/NetService 封装了大量日志,但有点过于冗余,比如每次请求都记录类型、内容、响应等,实际业务场景下,日志量太大会影响性能。建议日志级别可配置,或者只在错误、慢请求时打详细日志,正常请求只保留最必要的信息,否则生产环境容易刷屏,重要日志反而淹没。
OAuthData 里的 URL 拼接方式有改动,原来是 "authorize"、"token" 等直接拼成,现在加了 "/" 前缀,这个要格外小心。如果 OAuth2BaseUri 末尾已经有 "/",拼接时会不会多出 "//",需要测试下,否则有兼容性隐患。另外 FormUrlReqData 里的字典构建方式也有变化,要注意序列化时的 null 和空字符串,确保不会影响实际请求。
OpenBrowserAsync 方法改了 UseShellExecute=false,原来是 true,这个可能影响 Linux/Mac 上的兼容性,需要多平台测试下,尤其是在非 Windows 环境下,Process.Start 的行为和权限不一样,可能直接导致认证流程无法弹窗。
AccountService 里缓存、状态管理没怎么动,但注意 _isLoaded、_cachedAccounts 这些字段在多线程场景下是否安全,尤其是 DI 后可能有多个 Service 实例,最好加锁或者用 Concurrent 集合。
还有一些小细节,比如 BoolToOnlineStatusConverter 的 Convert 方法签名变了(加了 nullable),这点没问题,但要保证 XAML 绑定时不会有类型不匹配异常。
总的来说,这次 PR 做了不少清理和重构,代码简洁了,但异常处理、HttpClient 池、业务状态表达和日志方面都还有提升空间。建议后续可以:
- 网络层直接用 DI 的 HttpClient,或者 IHttpClientFactory,自己造池子反而容易踩坑。
- 异常和业务状态分离,DeviceFlow 相关不要全用 Exception,Result 类其实很有用,建议保留。
- 日志要做级别和策略控制,别全量输出,生产环境容易刷屏。
- OAuth2 URL 拼接和表单参数要多做兼容性测试,尤其是和第三方服务对接时。
- OpenBrowserAsync 要多平台测试,尤其是非 Windows 环境。
- AccountService 的缓存和状态管理要考虑线程安全。
- 最好能补一套单元测试,覆盖各种异常和边界情况,确保新网络层在各种场景下都能正常工作。
最后,这次改动比较大,建议合并前多做回归测试,尤其是 Microsoft 认证的完整流程和各种异常分支,避免上线后出现细碎问题。整体思路是对的,但细节上还得继续打磨,别因为重构而丢了原有的健壮性。希望这些建议能帮到你们,代码写得越来越好!
这个前期想的就是用
听你这么一说,要不然还是变成原来的
直接继承
会改
你写的欸,怎么丢到我头上搞了……
真是老爷爷啊(划掉) |
改成result还是算了,既然这样能跑就先这样吧,要不然改来改去太麻烦 |
那这个PR我就先Draft了,你先帮忙处理一下,依赖这个的相关计划也推一下。我去干别的了(例如UI) |
Refactor/Netwrok
概述
这个PR重构了网络类的实现,提供了两种方式以进行网络通信
修改
Net
类INetService
和NetService
StaticNet
HttpClientPool
使用方法
(抄的README)
INetService和NetService
概述
INetService 是一个基于依赖注入模式的 HTTP 客户端服务实现,提供了丰富的 HTTP 请求功能,包括发送普通请求、发送 JSON 数据以及处理响应。
使用说明
构造 NetService 实例
NetService 需要通过依赖注入来使用。
发送 HTTP 请求
注意事项
HttpRequestException
。StaticNet
概述
StaticNet 是一个静态类,提供了简单易用的 HTTP 客户端服务功能,适合快速实现 HTTP 请求。
使用说明
发送 HTTP 请求
注意事项
HttpRequestException
。