似乎 MVVM 难以调试,至少相对于 MVP ,是网上的普遍看法。具体体现在哪儿呢?我之前用过 MVP 模式,最近在看 MVVM 。
bug 变得难以调试,当遇到了异常,可能是 view 的问题,也有可能是 model 的问题。数据绑定使得 bug 快速传递到其他地方,要定位原始出问题的地方就变得不那么容易了。
Debugging is not easy in MVVM due to the complex layering patterns and the architectural style.
感觉 MVVM 模式很好啊:view 和 viewmodel 在很大程度上是解耦合的,也就方便了 view 的单元测试,为什么还会难以调试呢?
是数据双向绑定导致的难以调试?但数据也可以 log 啊,可以把 view 依赖的 viewmodel 的数据条目打印出来,时机就是这些数据变化时。也就几行代码的事。
1
nicevar 2022-01-03 16:55:47 +08:00
至少在 Android 的上面这个东西不是太好用,我是在工作上用 MVVM ,自己的项目不会用,比如 dataBinding 这玩意稍微有点问题导致程序挂掉了,几乎没有任何有效信息,没有经验的人对此毫无办法,浪费大量时间在这上面不值得,特别是一个人接触一个这类项目,恰巧升级了 sdk 版本触发了这么个 bug ,会搞到崩溃。
对于客户端来说,模块细分化可以,但是这种所谓的高大上模式带来的收益极为有限,现在很多人把客户端开发搞得跟服务器开发一样,就好像前端圈,非得往复杂的方向整,就浪费在框架上的时间项目都能开发完成一半了,我看 google 自己都懒得用 MVVM 这东西吧。 |
2
nicevar 2022-01-03 16:58:49 +08:00
难以调试是指报错信息有限,会严重误导开发者,你开 log 没用,离问题十万八千里的地方就挂了,要 log 有啥用?如果这个项目是你一直开发维护的还好,你很轻松能定位,但是你如果接受一个项目,就如上面我所说的,只是升级了 sdk 版本就挂了,然后茫茫代码中,你没有太多套路可以用,只能不断屏蔽代码缩小范围来定位问题,岂不是浪费时间。
|
3
Buges 2022-01-03 17:08:15 +08:00 via Android
双向绑定相比起单向传递,开发起来方便,但状态随意扩散到,父子组件耦合,确实不好调试。
|
4
sillydaddy OP @nicevar 没有看过 Android ,目前从 SwiftUI 开始了解的。
看到 https://jeremybytes.blogspot.com/2012/04/overview-of-mvvm-design-pattern.html 有个说法是: Consequence: Errors Move from Compile Time to Run Time 我理解的它的意思是:编译时只检查绑定的类型(甚至不检查),所以导致在绑定了错误的数据源时,仍能编译通过,但运行时就 error 了? |
5
SmaliYu 2022-01-03 18:10:28 +08:00 1
说实话,我还是比较喜欢 MVP ,比较纯粹……
|
6
railgun 2022-01-03 23:09:36 +08:00
难以调试应该是指调试器堆栈这些。打 log 是最后的 debug 手段了吧。
viewModel 和 view 之间松耦合,导致他们之间的调用关系不是那么明显。 |
7
AItsuki 2022-01-04 01:02:56 +08:00 1
我在 databinding 中写了一串中文,一直给老子报错,花了两天时间才定位到问题。谁能想到中文导致报错呢,而且不是所有中文都会。
另外就是用 mvvm 得到了什么,我将数据源多变换几成我同事能叫我爹,垃圾代码无论什么架构都救不了,写的好 mvc 都妥妥的,不过要是测试比较规范的话 mvp 比较好使。 一堆人连 mvvm 好在哪都讲不清楚就直接用,写了一坨不知道什么鬼东西,简单的事情非要绕几个圈。 |
8
omysho 2022-01-04 01:31:38 +08:00 via iPhone
|
9
omysho 2022-01-04 01:38:34 +08:00 via iPhone 1
从引用的段落来说,我给个例子
最近开发 Android 的时候遇到一个 Bug ,就是有些情况下列表显示的数据就是不对。 一开始以为是自己的数据流和状态管理,也就是 model 层,出了问题,打了 N 多 log ,一层一层追查,最后发现我的数据层传出来的数据是对的! 花了半天时间发现自己的数据居然没有问题,那就只能是,数据给到 UI 组件了,但是就是不显示。 最后经过一阵删代码查问题,发现是 MotionLayout 和 RecyclerView 之间不对付导致的,找到 google issue tracker 用了一个 workaround 最后才解决 所以问题是啥,就是解耦之后,就不知道 Bug 出自哪里了,所以就得到处追查 |
10
AItsuki 2022-01-04 09:25:15 +08:00
@omysho 感谢,我说的就是前两年的例子,databinding 是安卓 mvvm 不可或缺的一个组件,除非你手动进行双向绑定,后面我都没用 mvvm 了。百分之 80 的原因在于 databinding 这个组件,百分之 20 原因在于强耦合的数据关系( MediaLiveData ),已经定义好的 LiveData 真的不敢乱改,还得检查一遍 databinding 。
不过以后 Compose 流行起来了估计 MVVM 应该挺合适的,目前的 mvvm 我只能说团队大时间多喜欢折腾的就用。 |
11
omysho 2022-01-04 09:45:14 +08:00 via iPhone 1
@AItsuki
Compose 实际上很类似于 Flutter 的 Bloc ,其基本思想就是 UI 接受状态,发射事件,作为被动显示层,只管由状态驱动的 UI 显示 VM 接受事件,发射状态,本质上就是一个状态机,其他架构中也叫 Store 其中其实并未有双向绑定的事情,所有的输入都是 Event ,所有输出都是 State ,他们不是同一个数据流 顺便一提,LiveData 也废弃了,现在 Google 主推 Flow ,Flow 比 LiveData 好的一点就是线程安全 |
12
janus77 2022-01-04 09:46:53 +08:00 1
因为绑定关系本身不可调试。
MVP 的框架下,你从一层传输数据到另一层,我是知道他调用了哪个接口的哪个实现类,debug 可以直接进去那一行。 而在 MVVM 的绑定关系下,我虽然知道这两者绑定,但是我 debug 是否真的进入这一行,以及进入的时候参数还是不是原来的那个(参考楼上那个问题),完全不受我控制了 |
13
wanguorui123 2022-01-04 10:15:29 +08:00
MVVM 有时候很难追踪依赖状态,MVP 不会出现这个问题因为我能准确的知道哪个方法操作了哪个组件的状态
|
14
zinwalin 2022-01-04 10:20:57 +08:00 via iPhone
好贴
|
15
charlie21 2022-01-04 10:37:45 +08:00
越原始越方便 debug
|
16
bg7lgb 2022-01-04 13:07:13 +08:00
flutter 搞 mvvm ,感觉挺方便的,model 层确定数据无误,bug 定位也很方便。
|
17
sillydaddy OP 看样子调试难,主要是因为 “Data Binding 对调试不可见” 导致的。
我现在觉得这很大程度上是开发习惯的问题:MVVM 中,view 和 viewmodel ,很容易进行单元测试或者说 mock 假数据测试,如果利用好这一点,很大程度可以避免不知道问题出在哪一方吧。 比如某个 view 显示出了问题,可以构造一个用来测试的 viewmodel ,或者仅仅是把真 viewmodel 中的某些数据替换成 mock 数据,尝试在 view 上复现出现的问题。 比如,在 SwiftUI 中,对于每个 View ,都可以马上构造一个或多个 Preview(可使用 mock 的数据),可即时预览,从而检测 View 的功能是否正常。这相当于是单元测试了。 |
18
huruwo 2022-01-04 16:17:05 +08:00
谷歌这种疯狂抛弃前技术
|
19
nicevar 2022-01-04 16:38:02 +08:00
@omysho 我只是用 dataBinding 举个例子,viewBinding 也是半斤八两,2022 年了,换汤不换药的,刚从一个大的项目下来,两派人为了争这点东西差点没干起来,最后就是一部人用一部分人不用,出了问题各自管理自己的代码。
我觉得这个东西简单的代码用无所谓,复杂的还是不要用了,特别是人员流动大的公司千万不要用。 |
20
xingstar 2022-01-04 18:08:21 +08:00
这是个好贴啊,楼上各位大佬已经说的很清楚了,少用 mvvm ,没啥用😂
|
21
forgottencoast 2022-01-04 19:36:26 +08:00
没用过其他的,就我有限的 WPF 经验来说,WPF 的 MVVM 挺好用的。
但是这东西确实增加复杂度啊。 |
22
hlayk 2022-01-05 10:23:51 +08:00
从个人的实际使用经历来看( Android ) MVVM 并没有什么不好调试 双向绑定的数据该加断点该加 log 加 log 遇到难以排查的 bug 多关注下 viewmodel 对象的 id 和相关的生命周期 这一套下来也没什么难以调试的 但是有一点 databinding 这玩意绝对会增加调试的难度 目前项目已经完全弃用 dataBinding 这一架构我们只关心数据的传递 但当数据流入到 dataBinding 中 debug 和 log 都加不了 何谈调试 当数据流向变得明确 当数据可被观测 当数据可被 debug MVVM 也就不存在难以调试的说法(以上只是个人的使用体验)
|