表现层的设计(二)——MVC如何处理复杂的界面元素
需求描述
一个比较复杂的页面,界面中包含的元素数据来自于许多个有关联或者无关联的表,然后我们要做的就是将数据呈现在界面上。
10年前大概都是这么干的
直接写一个复杂的SQL语句,返回一个包含所需数据的二维表,然后直接与界面开始绑定。
简单、粗暴。
今天的现状
信息化解决方案的普及,我们接到的企业应用项目很多都是在旧系统无法满足需要的情况下扩展,业务功能也将建立在原来的基础上变得更加复杂。
所以,为了解决系统复杂所带来的困惑,人们开始从2层逻辑架构到n层发展。
分出数据访问层,使得数据提供得以重用。分出业务逻辑层,使得业务逻辑得以重用。
遇到更加复杂的业务,使得领域驱动设计开始流行,它将更多的业务逻辑内聚在领域模型里面,使得更多的业务逻辑得以重用。
引出了问题
1、许多人使用了ORM工具之后,认为它只能处理简单的功能,或者认为它适合做做界面上只有单个表的增删改,总之认为它不够灵活,其实ORM工具的Model只是一个业务层的东西,不是表现层的Model。
2、碰到这种界面元素复杂的问题,就觉得n层架构根本就是扯淡,有想直接上来一条SQL语句解决问题的冲动。
我们该如何解决
1、界面元素跟单个实体对应的情况。
这种情况在微软官方的DEMO中经常出现,ASP.NET MVC 5+EF6能够自动生成增删改列表3个页面,没什么好说的。
经常容易误导我们,以为MVC中的M指的只是实体类,其实M还可以指实体的服务类,实体的服务类里面包含业务逻辑的处理。
其实M指的是业务逻辑层,不一定只包含单个实体,很可能是多个有关联的实体,或者叫聚合根。
2、界面元素跟多个有关联的实体对应的情况。
这种情况就是上面提到的聚合根,业务层包含一定的逻辑,最后返回一个聚合根给控制器(C)。
视图(View)只需要一个实体就能搞定。
3、更为复杂点的,界面元素跟多个无关联的实体对应的情况。
这种情况下,我们需要创建一个ViewModel,然后用它组合多个无关联的实体。
把握一个原则,业务类对应的是业务模型,ViewModel对应的是每个View。
所以上面两种处理方法只是界面元素简单的情况下减轻工作量的做法,而理论上是需要一个View对应有一个ViewModel。
4、再复杂一点,或者不止一点。
好吧,真的足够复杂的话,那就无视一切理论吧,原生SQL、存储过程、无分层,随便了。
业务逻辑写在数据库,还是写在应用程序,这取决于纵向的负载均衡,需要智慧与经验。
主题是表现层,所以不讨论数据库该不该处理业务逻辑的问题。
总结:
当界面元素比较复杂时,试着创建一个ViewModel来组合业务类去磨平它。