今天上午看到InfoQ上的文章《.NET的MVVM框架》,当时就有写点什么的冲动,但不知道从哪里开始,就不了了之了。后来在博客园上又看见转载,两边都是一样,一条评论都没有,实在忍不住,就写了条评论在InfoQ的文章下,后来又觉得做MVVM实践这么长时间了,眼看要不做了,写篇博文,权当总结,与园友共讨论之。
最开始接触MVVM,是从我刚来万网开始的,那时候的我刚刚做了将近一年的Silverlight,刚刚出来工作不到两年,对什么“设计模式”之类的还是刚刚接触,那时候,还是很幼稚的我,凭借在方正的Silverlight开发经验,来到了万网,开始新的工作。
新的工作仍然是Silverlight开发,刚来的第一天就听到了一个我之前只是草草看过的概念——MVVM。当时一起做Silverlight开发的只有三个人(另两个兄弟,希望你们也能看到这篇博文),他们俩对MVVM了解的挺多的,不甘落后的我就开始废寝忘食地钻研MVVM。从简单实现,到Prism,到自己设计接口,实践中一次次地痛苦,一次次的失败,一次次地讨论,一次次地实践,现在回想起来,那段日子竟是我在万网最快乐的日子。
使用新技术改造老系统的难度本身就很大,再加上新模式的实践,我们遇到了很大的困难,最开始,我们就是与老代码做斗争,包装了一层又一层,没办法,一步一步艰难地往前走。遇到的问题,比如说数据模型没有属性改变通知、Silverlight端的底层只支持同步访问(我们不能直接访问WCF,有人封装好)等,都一一想办法解决了。
后来,我被调到另一个项目组做组长,其中有一项任务就是努力做好MVVM实践(在此感谢那位领导)。这个组中,有一个专职的XAML开发(在此感谢你),这对我的帮助很大,因为验证MVVM实践是否成功的最直接办法就是让一个不懂C#只懂XAML的人去完成所有的用户界面(包括交互)制作,如果他完美地完成了,那么你的实践在很大程度上程度上来说就是成功的,否则就一定是失败的。(注:这里,Action、Behavior的开发还是需要C#开发协助的,XAML开发要向C#开发提需求。)
她做到了(没错,是“她”)!她很好地完成了用户界面制作的工作,只需要一开发向她提供少量的代码支持就可以,从这个角度上说,我们取得了初步的成功。
不过做到这一点之后,我开心不起来,为了实现这个目标,我们做的筋疲力尽,在原有的底层上又包装了一层,数据服务、查询表达式等等统统包装了一层,从数据服务层往上看,哇,赏心悦目,干净整洁,MVVM的大楼!但是往下看,数据服务端为了简化上层的开发,做了很多牺牲,说白了,代码很乱,充满了危险的信号,这个,有老代码的问题,当然也有我的问题。
再后来,就当我们的实践有了基本的框架,要开始做功能的时候,我在下班的时候以30KM/h的速度与一辆旅游大巴车相撞(这一天刚好是我来万网一年整),左足跟软组织开放性外伤,住院8天回家养伤三个月。命大,足跟愈合了,三个月后,我又回到了公司,这时候,一切都陌生了。打开原来我熟悉的代码,有一些凄凉,甚至有一些陌生,我的MVVM,现在是这个样子了。
废话好像多了,再多就变成回忆录了,但是博客园上还是要写技术博文的。基于InfoQ上的那篇文章,我写了条评论,写了部分我们做MVVM实践时要把握的原则,这里再次总结原则和要点如下:
1 不要在View的Code-Behind中添加任何代码,除非这段代码没有任何复用性且只与当前页面交互逻辑有关;
2 ViewModel的设计要面向业务,面向数据会增加系统实现的复杂性,面向视图会降低ViewModel的可复用性;
3 ViewModel中不能掺杂任何与界面交互逻辑相关的东西(比如说IsExpanded,ShowDialogCommand之流);
4 Action/Behavior做为团队整体的积累,很重要,要保证质量,积累下来的东西要保证是可复用的;
5 ViewModel和View同时面向需求去设计,这样就能保证最终提供给View的ViewModel能够实现需求,不要让ViewModel为了View去做改变,一切看需求;
6 功能性的东西,可以封装到Command中,由ViewModel组装相应的Commands来实现某种功能;
7 ViewModel和Command粒度的划分要根据系统复杂度确定,简单的系统,粒度太细会增加复杂程度;
8 对于老系统改造来说,底层和数据层都要有大的改变,这是必然的;Silverlight使用同步方式与服务器交互是一种错误;
9 团队中所有成员对MVVM的认知要基本一致,否则会做出来的东西,你自己看吧,你自己都不认识;
10 严格的代码审查是很有必要的,毕竟这是一种尚未成熟的模式的实践,团队成员对模式的理解稍有偏差就会对代码产生非差大的影响;
还有很多啦,当然这也都是我浅薄的经验的总结,如有错误或不同意见,请大家批评指正,也欢迎大家讨论。
另,祝好。