关键词 并行开发 代码复用 关注点分离
经典的 MVC 架构模式
MVC 架构模式是经典设计模式中的经典,是一种编程的方法论。具有高度抽象的特征,经典 MVC 用简单的定义体现出解决复杂通用问题的办法,只有不断思考和体会才能用来解决不同情况下程序设计所遇到的问题。
MVC 不能脱离具体的框架而独自存在,把握抽象必须用具体;把握具体的内在结构和外在关系只能用抽象。
在前端领域中有代表 MVC 的 Anguler、代表 MVVM 的 Vue、和代表单向数据流的 React 都是很棒的前端框架,分别代表了一种具体的设计模式应用,在不同的应用场景中使用对了框架才能把这些框架的特性充分的发挥出来,如果只是从字面上找对应,Anguler 才是 MVC 的代表,Vue 显然不是 MVC 的代表,为什么我要选用 Vue 来做 MVC 架构模式呢?下面就来说一下为何这么做。
背景
我所在的部门业务场景上是分客群分产品的, 产品需求上迭代非常快,全场景一年要发布 120 多个版本,技术架构主要考量以下几点:
产品稳定性
多产品并行开发,支持 4 -10 个产品线独立开发部署
多产品公共功能可复用,保证开发效率
提升用户体验
技术架构本身的生命周期取决于业务的生命周期,好的架构模式应该是模块化的,可以针对其中的一个模块来进行优化升级,延长技术架构的生命周期就会节约很多成本。
选择 Vue
1. 足够的小巧,轻量,关注点聚焦,不会干扰整体项目设计架构;同时也有全家桶来做关注点分离,需要更多能力时全家桶中有可选择的项,减少重新造轮子。
2. 上手成本低、开发效率也很高
3.Vue 生态成熟和有庞大的开发者群体
不选 Angular 的原因:个人角度还是很喜欢 Angular,但 Angular 也有一些问题,如大版本发布太快和变化太大;大而全,这是优点也是缺点,缺点就是设计过重不利于每个团队根据实际情况基于 Angular 来重新设计架构,换掉其中的一部分设计,也很难让团队成员理解和适应。
不选 React 的原因:因 Facebook 的开源项目 React 嵌入了竞争防止协议,留下比较大的法务隐患,17 年 9 月内部就抛弃了 React 框架,已经使用 Ract 的项目也要限定期限改为其他框架。即使后来 FaceBook 的开源协议有所改善,但这种事情还是让大家心留余悸,不能再提了。
经典 MVC 回顾
MVC 全名是 Model View Controller,是软件工程中的一种软件架构模式,把软件系统分为三个 基本部分:模型 (Model)、视图(View) 和控制器(Controller)。
是一种软件设计典范,用一种业务逻辑和数据显式分离的方法组织代码,将业务逻辑聚集到一个部件里面,在界面和用户围绕数据的交互能被改进和个性化定制的同时而不需要重新编写业务逻辑。MVC 被独特的发展起来用于映射传统的输入、处理和输出功能在一个逻辑的图形化用户界面的结构中。
Model(模型)是应用程序中用于处理应用程序数据逻辑的部分。通常模型对象负责在数据库中存取数据。
模型表示企业数据和业务规则。在 MVC 的三个部件中,模型拥有最多的处理任务。模型与数据格式无关,这样一个模型能为多个视图提供数据,由于应用于模型的代码只需写一次就可以被多个视图重用,所以减少了代码的重复性。
View(视图)是应用程序中处理数据显示的部分。通常视图是依据模型数据创建的。
视图是用户看到并与之交互的界面。MVC 好处是它能为应用程序处理很多不同的视图。在视图中其实没有真正的处理发生,不管这些数据是联机存储的还是一个雇员列表,作为视图来讲,它只是作为一种输出数据并允许用户操纵的方式。
Controller(控制器)是应用程序中处理用户交互的部分。通常控制器负责从视图读取数据,控制用户输入,并向模型发送数据。
控制器接受用户的输入并调用模型和视图去完成用户的需求,所以当单击 Web 页面中的超链接和发送 HTML 表单时,控制器本身不输出任何东西和做任何处理。它只是接收请求并决定调用哪个模型构件去处理请求,然后再确定用哪个视图来显示返回的数据。
MVVM 架构模式
MVVM 模式是工程师在解决 WPF 应用程序开发复杂度时提出的解决方案,它实现了 View 和 Model 的自动同步,开发者不需要再手动的绑定输入监听和手动的将数据结果展示在 view 上,这就是双向数据绑定的优势,后来 Backbone、Vue 等都是 MVVM 模式的前端框架。
ViewModel 解决了 View 和 Model 之间转换的开发效率问题。但是 ViewModel 内部的复杂度又变成了新的问题,其中一个问题就是双向数据绑定劣势。在双向数据绑定中,Model(可以理解为状态的集合)中可以修改自己或其他 Model 的状态,用户的操作(如在输入框中输入内容)也可以修改状态。这使的改变一个状态有可能会触发一连串的状态的变化,最后很难预测最终的状态是什么样的。使得代码变得很难调试。
为了解决这个问题便有了后来的 Vue 单向数据流的解决方案 -Vuex。在复杂度较高的业务上使用单向数据流来解耦 View 和 Model 的关系。
可以看出经典 MVC 架构模式的重点是要解决业务逻辑复用和数据显式分离,前端 MVC 本质要解决的还是这两点,不同的是前端用组件化和 MVVM 分别来解决业务逻辑复用和数据显式分离,MVC、MVVM 都要解决 MV 这两层的的问题。前后端分离后、前端使用单页应用就可以完成用户界面部分的管理,此时在前端架构中需要有一层来管理页面切换这就是前端 MVC 的 Controller 控制层。
MVC 和 MVVM 本质上这是两种架构模式,是为了解决不同场景遇到的开发问题。两者解决的问题有相似之处,MVVM 中的 ViewModel 和 MVC 中的 Controller 作用有些相似。用 Vue 框架的项目引入 Vuex 后 ViewModel 的作用被弱化,MVVM 和单向数据流都无法反映整个框架的架构模式。同时整体架构还要解决单页应用等问题,更需要有一个准确的理论模型,从而选择 MVC 架构模式来做项目架构更适合实际情况。
front MVC 架构定义
代码库结构图
在业务层(不包括基础组件)和经典 MVC 想比 Front MVC 的核心由 Model 变成了 View。View 层的设计是重点,基础组件尽量使用组件特性和 MVVM、避免过度设计造成层级复杂度变大;业务组件可以用 EventBus 的方式来处理跨层级交互的问题。Model 层由 Vuex 来管理,Vuex 适合数据量大并且函数集中处理,管理接口数据很合适;以便明确各种方式的最佳实践范围。
Model(模型)是应用程序中用于处理应用程序状态管理和数据交互的部分。主要由状态管理 Vuex 和数据交互 axios 实现。
View(视图)是应用程序中业务逻辑处理和内容展示的部分。不同于经典 MVC 中的 View,Front MVC 的 View 层业务逻辑会比较重,这是由于前端的复用主要体现在组件上,前端框架 Vue 的 Global API 一系列特性也非常好的支撑这种组件化业务需求。这里的 View 层主要有基础组件库、公共组件库、产品组件库组成,其中前两个库是可以复用的。
Controller(控制器)是应用程序中处理用户交互的部分。不同于 MVC 中的 Controller,Front MVC 的 Controller 层是通过路由机制加载 View 主要是有 viewRouter 来实现,再有 View 根据交互逻辑来控制 Model 层的调用。在这里 View 是应用程序的核心部件。
这样设计的特点:
首先实现了单页应用,用户体验交回前端管理
MVC 各层是模块化的,可灵活调整和复用
层级划分清晰,利于用最佳实践实现
Model 层数据可复用,跨页面公共数据根据情况可只调用一次
View 层可复用
并行开发模式
并行开发效率高,但产品多、开发人员多、发版频繁一定会造成冲突和相互影响,必须重点关注保证产品稳定性。控制好公共部分的改动频率和修改权限。
解决方法:
各产品库的 node_module 依赖项统一管理,兼容公共部分依赖项。
业务公共库各产品负责人有修改权限,既保证公共部分协同开发,也保证公共部分稳定。
基础组件库精心打磨,控制发版频次。
只在产品库中编译项目, 公共库使用 git sub module 的方式引入,各产品单独发布部署包。
各产品单独部署。
结论
只要能解决问题,架构应该是越简单越好,就像经典 MVC 架构模式一样简洁,一样有力量。不断总结分析,寻求不同的解决方法,设计时整体考量,经常在抽象和具体之前切换角度思考,才能兼顾开发效率和技术支撑。
本文是从项目整体设计上对 MVC 架构模式进行了一个实践总结,欢迎大家交流指正!