win10 uwp MVVM 语义耦合

最近在我写的框架,小伙伴告诉我,可能有语义耦合,那么本文就来告诉大家,为什么会出现语言耦合

之前我写了一个轻量的框架,参见win10 uwp MVVM 轻量框架 。在使用的过程,发现了这个框架可以让开发者写出语义耦合的代码。

在开始讲框架之前,先让我告诉大家,什么是语义耦合。

例如有一个框架,在框架的代码都没有任何的耦合,如 View 的界面和 ViewModel 是分开在两个工程,而且只有 View 引用 ViewModel ,这样从静态的代码分析可以说,ViewModel 没有耦合 View 。但这是不是真的就没有耦合?实际上可能还是有语义的耦合。

在小伙伴使用框架,但是对 MVVM 的理解不是很深的时候,就容易写出下面的代码

ViewModel:

发送 刷新 列表消息

View 

处理 刷新列表消息

这时,因为 ViewModel 写出了刷新列表的消息,所以刷新列表这个界面相关的消息就耦合了界面。也就是在 ViewModel 是处理了部分的界面的逻辑。

在很多的代码,包括继龙大神的、于大神的代码,发现了在 ViewModel 使用了 Visibility 的属性,需要知道 Visibility 是界面的属性,如果界面绑定了 Visibility 那么 ViewModel 就需要对 Visibility 处理。这时的界面是需要写 ViewModel 的开发者知道的。这时界面修改的话,例如原来在条件下需要 Visibility 隐藏的代码就需要修改为不隐藏。这时修改界面就需要修改 ViewModel 。

如果在 ViewModel 耦合了界面的控制,那么为什么需要 ViewModel ? 实际上的 ViewModel 是抽象页面,所以不能对 ViewModel 添加对界面控制的代码。在太子的博客语义耦合已经有说到关于 Message 耦合的问题。同样也给出一些解决方法。

下面我来告诉大家一些比较好的处理方法。

在几乎所有主流的 MVVM 框架,都提供了 Message 给 ViewModel 和 View 通信。而且在我的框架用了 Message,所以对 Message 是比较难写的一点。如果限制很多,那么很多开发者就不会使用,解决这个框架不好用。如果给的功能太多,那么容易出现语义耦合,而且使用这个功能做框架设计没有提供的功能。

需要和大家分享一个故事,为什么 微软 把Action 的参数提供了 16 个?因为他需要考虑全世界所有的开发者。但是一般的开发者建议使用的参数只有两个,但是在一个足够通用的框架,是需要做到对少数的开发者也可以使用。所以不要认为只要框架提供了,就可以使用。一个好的开发者会去阅读框架的文档,然后使用框架开发者希望使用的方式开发。但是一个好的框架是开发者不需要去读文档,看到了框架就会使用。这是矛盾的,但是和框架开发者的能力有关。微软框架大部分都是很好的,但是也有一些代码写的很差。最近我在写高性能笔的时候就发现了他的代码的问题,已经帮他修复了,但是现在微软几乎不做 .net Framework 了,把他的很多代码都放在 .net core ,然后就经常看到有大神修改了算法,提高了性能。

回到问题,如何在开发中解决 MVVM 的语言耦合,实际上这不是一个技术问题。建议的方法是让开发者的代码经过审查,现在在开发的时候,所有的代码都需要提MR,在来源的开发中,也是需要提MR,这样就可以容易发现在代码中存在的语义耦合。现在通过工具是难以发现的。

如果发现了存在语义耦合,那么如何解决?

这个需要分析一下,一般做法是让具体的命名写为抽象。如上面的代码,从ViewModel 告诉 View 刷新列表,为什么需要 ViewModel 知道 View 需要刷新列表,他可以使用一个抽象的命名,例如告诉 View 现在更新了数据。于是 View 根据ViewModel 的消息进行刷新列表,这样就不会出现 ViewModel 的语言耦合。

但是很多的代码都可以使用状态来获得刷新和修改,所以这时就不需要使用消息。

另一个建议是最好不要在 ViewModel 定义界面的控制的方法,例如 Visibility ,不可以让ViewModel 去控制 View 。在微软提出的就说到,ViewModel 是驱动数据,所以 ViewModel 只是转发数据,这样才可以减少耦合。

一个项目使用了框架会比不使用框架的可维护要好很多,即使使用的时候存在一些问题,但是也比不使用好。

参见:语义耦合(Semantic Coupling) - walterlv


本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏xingoo, 一个梦想做发明家的程序员

oracle多用户并发及事务处理

多用户并发访问 事务:作用于某些数据的一个不可分割的操作 锁:写锁、互斥锁(仅能被一个进程使用)      读锁、共享锁(可被多个进程使用) 更新丢失 脏读 不...

27970
来自专栏武培轩的专栏

《从Paxos到Zookeeper:分布式一致性原理与实践》第一章读书笔记

第一章主要介绍了计算机系统从集中式向分布式系统演变过程中面临的挑战,并简要介绍了ACID、CAP和BASE等经典分布式理论,主要包含以下内容:

13110
来自专栏小白安全

Janus高危漏洞深度分析

一、背景介绍 近日,Android平台被爆出“核弹级”漏洞Janus(CVE-2017-13156),该漏洞允许攻击者任意修改Android应用中的代码...

36690
来自专栏软件开发

WebSocket与消息推送

B/S结构的软件项目中有时客户端需要实时的获得服务器消息,但默认HTTP协议只支持请求响应模式,这样做可以简化Web服务器,减少服务器的负担,加快响应速度,因为...

90150
来自专栏Android干货园

Android Studio导入github项目详解

版权声明:本文为博主原创文章,转载请标明出处。 https://blog.csdn.net/lyhhj/article/details/48...

1.5K20
来自专栏LhWorld哥陪你聊算法

【Spark篇】---Spark中Shuffle文件的寻址

Spark中Shuffle文件的寻址是一个文件底层的管理机制,所以还是有必要了解一下的。

14950
来自专栏Android机动车

使用Gradle实现多渠道打包

这里我们主要用到gradle文件中的buildTypes和productFlavors,今天我们主要研究下它俩。

7810
来自专栏菜鸟程序员

Janus高危漏洞深度分析

18430
来自专栏向治洪

Android资源混淆打包方案

概述 我们知道在Android的打包过程中,有一个步骤是压缩,也是为了减少apk包的大小,其中在压缩的过程中,很大一部分就是对资源的压缩,除了系统的压缩方案之外...

452100
来自专栏编程

修复 Linux/Unix/OS X/BSD 系统控制台上的显示乱码

有时我的探索会在屏幕上输出一些奇怪的东西。比如,有一次我不小心用 cat 命令查看了一下二进制文件的内容 —— cat /sbin/*。这种情况下你将无法再访问...

22760

扫码关注云+社区

领取腾讯云代金券