MVC还是MVVM?或许VMVC更适合WinForm客户端
最近开始重构一个稍嫌古老的C/S项目,原先采用的技术栈是『WinForm』+『WCF』+『EF』。相对于现在铺天盖地的B/S架构来说,看上去似乎和Win95一样古老,很多新入行的,可能就没有见过经典的C/S架构的系统。事实上,作为企业信息管理系统,包括ERP/CRM/SCM等,桌面客户端还是很OK的。
这次重构原定的目标有两个:
1、客户端还是WinForm不变,但使用MVC模式重写;
2、WCF改成WebAPI。
经过2周时间的尝试和探索,重构计划变更为:
1、使用VMVC模式来重构WinForm客户端;
2、用WCF实现伪WebAPI,其本质还是个WCF服务,但实现了RESTful风格的WebAPI。
这次和大家分享我对客户端架构的一些探索,就不展开服务端相关的话题了。那么,什么是VMVC呢?呵呵,这个是我发明的新名称,和MVC的区别在于用ViewModel替换了Model。ViewModel和View之间实现双向数据绑定,View上面的交互产生的操作指令,还是由Controller接收,然后通过对ViewModel的操作,更新View的数据。
简单地说,就是ViewModel负责数据流,View负责显示和接受用户指令,而Controller则居中调度。示意图如下:

由于实现了数据双向绑定,所以在一定程度上简化了数据的存储。只需要执行ViewModel上的Save()方法,就可以将新的数据通过WebAPI存储到数据库了。
ViewModel的职责非常明确,就是一个数据流引擎!所以基本上都是Load()、Save()、Show()、Refresh()、Close()这些无脑方法,一丁点的业务逻辑都木有。非常适合有一定编程经验,但不了解业务逻辑的程序员编写。
而View就更简单了,完全由VS的窗体设计器生成。UI设计师从此不需要PS了,根据产品原型直接拖控件就OK。
最后,所有的业务逻辑都写在Controller里面,这样就为自动化测试提供了可能。测试工程师只需要编写一段测试代码替代Controller,同时对View的数据进行注入就可以跑单元测试。
下面是我用于尝试这种模式的示例,希望能够起到抛砖引玉的作用。
代码结构:

Controller(部分代码),通过订阅View上面的确定按钮点击事件实现用户操作的委托:
/// <summary>
/// 修改服务器配置
/// </summary>
private void ConfigServer()
{
_SetModel = new SetModel(); // 订阅确定按钮点击事件
_SetModel.View.ConfirmButton.Click += SetConfirm_Click;
_SetModel.ShowDialog();
} /// <summary>
/// 点击确定按钮
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void SetConfirm_Click(object sender, EventArgs e)
{
if (!_SetModel.Test()) return; _SetModel.Save();
_SetModel.Close();
}
ViewModel:
using System;
using System.Windows.Forms;
using Insight.Utils.Client;
using Insight.Utils.Common;
using Insight.WS.Client.Common.Utils;
using Insight.WS.Client.MainApp.Views; namespace Insight.WS.Client.MainApp.Models
{
public class SetModel
{
public LoginSet View = new LoginSet(); private string _Address = Config.BaseAddress();
private string _Port = Config.Port();
private bool _SaveUser = Config.IsSaveUserInfo(); /// <summary>
/// 构造方法,初始化控件初始值
/// 通过订阅事件实现双向数据绑定
/// </summary>
public SetModel()
{
View.AddressInput.EditValueChanged += AddressChanged;
View.AddressInput.Text = _Address; View.PortInput.EditValueChanged += PortChanged;
View.PortInput.Text = _Port; View.SaveUserCheckBox.CheckStateChanged += SaveUserChanged;
View.SaveUserCheckBox.Checked = _SaveUser;
} /// <summary>
/// 显示对话框
/// </summary>
public void ShowDialog()
{
View.ShowDialog();
} /// <summary>
/// 关闭对话框
/// </summary>
public void Close()
{
View.DialogResult = DialogResult.OK;
View.Close();
} /// <summary>
/// 测试服务器连通性
/// </summary>
/// <returns>bool 是否通过连通性测试</returns>
public bool Test()
{
var url = $"http://{_Address}:{_Port}/commonapi/v1.0/test";
var result = new HttpClient(url).Request(Params.Token);
if (result.Code != "") return true; Messages.ShowError("请配置正确的服务器地址和端口号!");
return false;
} /// <summary>
/// 保存设置
/// </summary>
public void Save()
{
if (!_SaveUser) Config.SaveUserName(string.Empty); Config.SaveIsSaveUserInfo(_SaveUser);
Config.SaveAddress(_Address, _Port); Params.InsightServer = $"http://{_Address}:{_Port}";
} /// <summary>
/// 服务器地址发生变化
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void AddressChanged(object sender, EventArgs e)
{
_Address = View.AddressInput.Text;
} /// <summary>
/// 服务端口发生变化
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void PortChanged(object sender, EventArgs e)
{
_Port = View.PortInput.Text;
} /// <summary>
/// 保存用户账号选项发生变化
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void SaveUserChanged(object sender, EventArgs e)
{
_SaveUser = View.SaveUserCheckBox.Checked;
}
}
}
MVC还是MVVM?或许VMVC更适合WinForm客户端的更多相关文章
- 还在纠结 Flux 或 Relay,或许 Redux 更适合你
重磅消息,Redux 1.0 发布,终于可以放心用于生产环境了! 在这个端应用技术膨胀的时代,每天都有一大堆框架冒出,号称解决了 XYZ 等一系列牛 X 的问题,然后过一段时间就不被提起了.但开发的应 ...
- Android App的设计架构:MVC,MVP,MVVM与架构经验谈
相关:http://www.cnblogs.com/wytiger/p/5996876.html 和MVC框架模式一样,Model模型处理数据代码不变在Android的App开发中,很多人经常会头疼于 ...
- MVC, MVP, MVVM比较以及区别(下)
上一篇得到大家的关注,非常感谢.一些朋友评论中,希望快点出下一篇.由于自己对于这些模式的理解也是有限,所以这一篇来得迟了一些.对于这些模式的比较,是结合自己的理解,一些地方不一定准确,但是只有亮出自己 ...
- MVC, MVP, MVVM比较以及区别
MVC, MVP和MVVM都是用来解决界面呈现和逻辑代码分离而出现的模式.以前只是对它们有部分的了解,没有深入的研究过,对于一些里面的概念和区别也是一知半解.现在一边查资料,并结合自己的理解,来谈一下 ...
- 浅析前端开发中的 MVC/MVP/MVVM 模式
MVC,MVP和MVVM都是常见的软件架构设计模式(Architectural Pattern),它通过分离关注点来改进代码的组织方式.不同于设计模式(Design Pattern),只是为了解决一类 ...
- [转]MVVM架构~mvc,mvp,mvvm大话开篇
MVP 是从经典的模式MVC演变而来,它们的基本思想有相通的地方:Controller/Presenter负责逻辑的处理,Model提供数据,View负 责显示.作为一种新的模式,MVP与MVC有着一 ...
- MVC,MVVM,MVP等设计模式的分析
从Script到Code Blocks.Code Behind到MVC.MVP.MVVM 三个模式按照大致的历史进程将这些概念进行划分: Script Code Blocks.Code Behind ...
- 前端mvc mvp mvvm 架构介绍(vue重构项目一)
首先 我们为什么重构这个项目 1:我们现有的技术是前后台不分离,页面上采用esayUI+jq构成的单页面,每个所谓的单页面都是从后台胜场的唯一Id 与前端绑定,即使你找到了那个页面元素,也找不到所在的 ...
- 浅谈MVC、MVVM的区别
一.概述 MVC,MVP,MVVM是三种常见的前端架构模式(Architectural Pattern),它通过分离关注点来改进代码组织方式.不同于设计模式(Design Pattern),只是为了解 ...
随机推荐
- SSH实战 · 唯唯乐购项目(下)
后台模块 一:后台用户模块 引入后台管理页面 创建adminuser表: CREATE TABLE `adminuser` ( `uid` int(11) NOT NULL AUTO_INCREM ...
- iOS---iOS10适配iOS当前所有系统的远程推送
一.iOS推送通知简介 众所周知苹果的推送通知从iOS3开始出现, 每一年都会更新一些新的用法. 譬如iOS7出现的Silent remote notifications(远程静默推送), iOS8出 ...
- 03.LoT.UI 前后台通用框架分解系列之——多样的表格
LOT.UI分解系列汇总:http://www.cnblogs.com/dunitian/p/4822808.html#lotui LoT.UI开源地址如下:https://github.com/du ...
- ASP.NET Core应用中如何记录和查看日志
日志记录不仅对于我们开发的应用,还是对于ASP.NET Core框架功能都是一项非常重要的功能特性.我们知道ASP.NET Core使用的是一个极具扩展性的日志系统,该系统由Logger.Logger ...
- 通过三次优化,我将gif加载优化了16.9%
WeTest 导读 现在app越来越炫,动不动就搞点动画,复杂的动画用原生实现起来挺复杂,如是就搞起gif播放动画的形式,节省开发成本. 背 景 设计同学准备给一个png序列,开发读取png序列, ...
- 【C#附源码】数据库文档生成工具支持(Excel+Html)
[2015] 很多时候,我们在生成数据库文档时,使用某些工具,可效果总不理想,不是内容不详细,就是表现效果一般般.很多还是word.html的.看着真是别扭.本人习惯用Excel,所以闲暇时,就简单的 ...
- Web安全相关(四):过多发布(Over Posting)
简介 过多发布的内容相对比较简单,因此,我只打算把原文中的一些关键信息翻译一下.原文链接如下: http://www.asp.net/mvc/overview/getting-started/gett ...
- 【JavaScript】javascript中伪协议(javascript:)使用探讨
javascript:这个特殊的协议类型声明了URL的主体是任意的javascript代码,它由javascript的解释器运行. 比如下面这个死链接: <a href="javasc ...
- MMORPG大型游戏设计与开发(攻击区域 扇形)
距离上次发布已经有了很长一段时间,期间由于各种原因没有更新这方面的技术分享,在这里深表遗憾.在MMO或其他的游戏中,会有针对各种形状的计算,通常在攻击区域里不会很复杂,常见的为矩形.圆形.扇形.今天分 ...
- sublime text 3 + python配置,完整搭建及常用插件安装
四年的时间,一直使用EmEditor编辑器进行Python开发,之前是做面向过程,只需要将一个单独的py文件维护好即可,用着也挺顺手,但是最近在做面向对象的开发,不同的py文件中相互关联较多,感觉单纯 ...