V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
sillydaddy
V2EX  ›  程序员

MVVM 难以调试体现在哪儿?

  •  2
     
  •   sillydaddy · 2022-01-03 16:37:23 +08:00 · 3249 次点击
    这是一个创建于 806 天前的主题,其中的信息可能已经有所发展或是发生改变。

    似乎 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 的数据条目打印出来,时机就是这些数据变化时。也就几行代码的事。

    22 条回复    2022-01-05 10:23:51 +08:00
    nicevar
        1
    nicevar  
       2022-01-03 16:55:47 +08:00
    至少在 Android 的上面这个东西不是太好用,我是在工作上用 MVVM ,自己的项目不会用,比如 dataBinding 这玩意稍微有点问题导致程序挂掉了,几乎没有任何有效信息,没有经验的人对此毫无办法,浪费大量时间在这上面不值得,特别是一个人接触一个这类项目,恰巧升级了 sdk 版本触发了这么个 bug ,会搞到崩溃。
    对于客户端来说,模块细分化可以,但是这种所谓的高大上模式带来的收益极为有限,现在很多人把客户端开发搞得跟服务器开发一样,就好像前端圈,非得往复杂的方向整,就浪费在框架上的时间项目都能开发完成一半了,我看 google 自己都懒得用 MVVM 这东西吧。
    nicevar
        2
    nicevar  
       2022-01-03 16:58:49 +08:00
    难以调试是指报错信息有限,会严重误导开发者,你开 log 没用,离问题十万八千里的地方就挂了,要 log 有啥用?如果这个项目是你一直开发维护的还好,你很轻松能定位,但是你如果接受一个项目,就如上面我所说的,只是升级了 sdk 版本就挂了,然后茫茫代码中,你没有太多套路可以用,只能不断屏蔽代码缩小范围来定位问题,岂不是浪费时间。
    Buges
        3
    Buges  
       2022-01-03 17:08:15 +08:00 via Android
    双向绑定相比起单向传递,开发起来方便,但状态随意扩散到,父子组件耦合,确实不好调试。
    sillydaddy
        4
    sillydaddy  
    OP
       2022-01-03 17:14:08 +08:00
    @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 了?
    SmaliYu
        5
    SmaliYu  
       2022-01-03 18:10:28 +08:00   ❤️ 1
    说实话,我还是比较喜欢 MVP ,比较纯粹……
    railgun
        6
    railgun  
       2022-01-03 23:09:36 +08:00
    难以调试应该是指调试器堆栈这些。打 log 是最后的 debug 手段了吧。
    viewModel 和 view 之间松耦合,导致他们之间的调用关系不是那么明显。
    AItsuki
        7
    AItsuki  
       2022-01-04 01:02:56 +08:00   ❤️ 1
    我在 databinding 中写了一串中文,一直给老子报错,花了两天时间才定位到问题。谁能想到中文导致报错呢,而且不是所有中文都会。
    另外就是用 mvvm 得到了什么,我将数据源多变换几成我同事能叫我爹,垃圾代码无论什么架构都救不了,写的好 mvc 都妥妥的,不过要是测试比较规范的话 mvp 比较好使。
    一堆人连 mvvm 好在哪都讲不清楚就直接用,写了一坨不知道什么鬼东西,简单的事情非要绕几个圈。
    omysho
        8
    omysho  
       2022-01-04 01:31:38 +08:00 via iPhone
    @nicevar
    @AItsuki

    现在 Databiding 已经 88 了
    databinding 依赖于 kapt ,kapt 已经只维护,不增新功能了,正全面转向 ksp

    所以 databinding 也是个老旧功能了,应该逐步用 viewbing 代替
    omysho
        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 出自哪里了,所以就得到处追查
    AItsuki
        10
    AItsuki  
       2022-01-04 09:25:15 +08:00
    @omysho 感谢,我说的就是前两年的例子,databinding 是安卓 mvvm 不可或缺的一个组件,除非你手动进行双向绑定,后面我都没用 mvvm 了。百分之 80 的原因在于 databinding 这个组件,百分之 20 原因在于强耦合的数据关系( MediaLiveData ),已经定义好的 LiveData 真的不敢乱改,还得检查一遍 databinding 。
    不过以后 Compose 流行起来了估计 MVVM 应该挺合适的,目前的 mvvm 我只能说团队大时间多喜欢折腾的就用。
    omysho
        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 好的一点就是线程安全
    janus77
        12
    janus77  
       2022-01-04 09:46:53 +08:00   ❤️ 1
    因为绑定关系本身不可调试。
    MVP 的框架下,你从一层传输数据到另一层,我是知道他调用了哪个接口的哪个实现类,debug 可以直接进去那一行。
    而在 MVVM 的绑定关系下,我虽然知道这两者绑定,但是我 debug 是否真的进入这一行,以及进入的时候参数还是不是原来的那个(参考楼上那个问题),完全不受我控制了
    wanguorui123
        13
    wanguorui123  
       2022-01-04 10:15:29 +08:00
    MVVM 有时候很难追踪依赖状态,MVP 不会出现这个问题因为我能准确的知道哪个方法操作了哪个组件的状态
    zinwalin
        14
    zinwalin  
       2022-01-04 10:20:57 +08:00 via iPhone
    好贴
    charlie21
        15
    charlie21  
       2022-01-04 10:37:45 +08:00
    越原始越方便 debug
    bg7lgb
        16
    bg7lgb  
       2022-01-04 13:07:13 +08:00
    flutter 搞 mvvm ,感觉挺方便的,model 层确定数据无误,bug 定位也很方便。
    sillydaddy
        17
    sillydaddy  
    OP
       2022-01-04 13:51:28 +08:00
    看样子调试难,主要是因为 “Data Binding 对调试不可见” 导致的。

    我现在觉得这很大程度上是开发习惯的问题:MVVM 中,view 和 viewmodel ,很容易进行单元测试或者说 mock 假数据测试,如果利用好这一点,很大程度可以避免不知道问题出在哪一方吧。

    比如某个 view 显示出了问题,可以构造一个用来测试的 viewmodel ,或者仅仅是把真 viewmodel 中的某些数据替换成 mock 数据,尝试在 view 上复现出现的问题。

    比如,在 SwiftUI 中,对于每个 View ,都可以马上构造一个或多个 Preview(可使用 mock 的数据),可即时预览,从而检测 View 的功能是否正常。这相当于是单元测试了。
    huruwo
        18
    huruwo  
       2022-01-04 16:17:05 +08:00
    谷歌这种疯狂抛弃前技术
    nicevar
        19
    nicevar  
       2022-01-04 16:38:02 +08:00
    @omysho 我只是用 dataBinding 举个例子,viewBinding 也是半斤八两,2022 年了,换汤不换药的,刚从一个大的项目下来,两派人为了争这点东西差点没干起来,最后就是一部人用一部分人不用,出了问题各自管理自己的代码。
    我觉得这个东西简单的代码用无所谓,复杂的还是不要用了,特别是人员流动大的公司千万不要用。
    xingstar
        20
    xingstar  
       2022-01-04 18:08:21 +08:00
    这是个好贴啊,楼上各位大佬已经说的很清楚了,少用 mvvm ,没啥用😂
    forgottencoast
        21
    forgottencoast  
       2022-01-04 19:36:26 +08:00
    没用过其他的,就我有限的 WPF 经验来说,WPF 的 MVVM 挺好用的。
    但是这东西确实增加复杂度啊。
    hlayk
        22
    hlayk  
       2022-01-05 10:23:51 +08:00
    从个人的实际使用经历来看( Android ) MVVM 并没有什么不好调试 双向绑定的数据该加断点该加 log 加 log 遇到难以排查的 bug 多关注下 viewmodel 对象的 id 和相关的生命周期 这一套下来也没什么难以调试的 但是有一点 databinding 这玩意绝对会增加调试的难度 目前项目已经完全弃用 dataBinding 这一架构我们只关心数据的传递 但当数据流入到 dataBinding 中 debug 和 log 都加不了 何谈调试 当数据流向变得明确 当数据可被观测 当数据可被 debug MVVM 也就不存在难以调试的说法(以上只是个人的使用体验)
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   3392 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 31ms · UTC 11:50 · PVG 19:50 · LAX 04:50 · JFK 07:50
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.