前端架构-分层而治,铁打的MV流水的C
大家好,我是Eluxjs的作者,Eluxjs是一套基于“微模块”和“模型驱动”的跨平台、跨框架『同构方案』,欢迎了解...
文前声明,以下推断和结论纯属个人探索,鉴于本人知识水平所限,谬误在所难免,恳请各位大佬不吝赐教...
为什么在web前端很少有人会提到分层架构,例如经典MVC架构,这是因为浏览器诞生之初就只是作为一个后端数据的GUI渲染器。也就是说整体来看,web1.0时代的整个web前端工程就是一个View层,而Model和Controller就是指后端,所以根本无需在web前端工程中去提什么MVC。
然而web生态发展到今天,浏览器越来越强大,赋能越来越多,甚至不亚于一个小型操作系统,这时候的Web前端早已不是当初简单的数据渲染器,随着PWA、小程序、快应用的推广,WebAPP已经和传统的“富客户端”没什么两样了。那么在这种趋势下,如果我们的Web前端架构还停留在View的时代,那么显然是落伍的。
View是最直观的、最原始的驱动源,解决了所有View的问题也就实现了WebApp的所有功能,前端开发人员的全部工作就是一个又一个的编写Component。正是因为这种以View为核心的架构思维,导致我们只为解决表层问题而架构,不去思考顶层设计,这也是很多Web前端工程经过几轮迭代和人员转手后,很难继续维护下去的根本原因。
近年来涌现出一些优秀的UI渲染框架,比如React/Vue/Anglar,它们很强大,可以干很多分内和分外的事情。正因为如此,更造成了开发者的惰性,将所有逻辑都直接以最原始的方式写在View中,不管是Mode还是Controller,不管是业务逻辑、还是渲染逻辑、还是存储逻辑、还是通讯逻辑、还是路由逻辑...所有各类逻辑叠加各种UI生命周期,全部都耦合在一个Component中。
从视图驱动到领域驱动
是时候改变我们的架构思维,从视图驱动升华到领域驱动。虽然视图驱动是最直观也是最简单的一种架构模式,但是我们不仅要解决问题,还要思考如何优雅的解决问题,这也好比是排版和设计的区别吧!
或者说,在项目野蛮生长的混沌初期你可以从下往上构建,所建即所得。但到了某个重构的时间点,你还是得站在顶部进行上层设计。
当然,这里有个默认前提,那就是需要长期维护的中大型项目,小而快的项目无需谈各种架构模式...
将UI框架拉下神坛
UI不是工程的全部,UI的指责只有2个:输入与输出,仅此而已。所以即便React/Vue再强大,你也应当仅把它们当成一个GUI工具,类似于Java Swing和.Net WPF,而非整个工程React/Vue一把梭。
~~ 敲黑板:UI只是指令的收集者、传达者、反馈者,而不应当成为指令的执行者。 ~~
应用的核心是业务逻辑
现在问你一个问题:
如果没有UI,你的应用可以通过命令来驱动吗?
你可能会怼我说,用户怎么可能会通过命令来使用我的应用,没有这样的业务场景,你这个假设是毫无意义的。然而,这种场景或许并不是为用户而设,而是为合作伙伴而设、为测试工具而设、为日志分析而设、为今后的扩展和生态建设而设...
再问你一个问题:
- UI说:应用要改版,皮肤、交互、页面组织都要调整,要多久?
- 产品说:把H5改改,做成小程序、APP吧,要多久?
- 经理说:React人太难招了,要不我们换成Vue吧,要多久?
- Leader说:Vue3出来了,我们升级为最新版吧,要多久?
- 架构师说:Svelte快到飞,我们重构为Svelte吧,要多久?
业务逻辑不变,仅调整UI和其运行平台,问你要多久?这个时候,如果你的全部逻辑都是耦合在某种特定的UI框架中的,那你只能是哀默之心大于死...
UI逻辑与业务逻辑分离
从早期的前后端一体化,到后面的前后端逻辑分离,在到这里我重提UI逻辑与业务逻辑分离,都只是顺着2件事件在做:让需要内聚的更内聚,让可以解耦的更松散。
业务逻辑抽象,UI逻辑具体:业务逻辑是抽象的数据模型,而UI逻辑则是抽象事物逐层泛化后的具体表现,它们两个本身就不再同一个Level上。
业务逻辑通用,UI逻辑特殊:UI逻辑通常需要借助于某个具体的UI框架而表达,而UI框架通常都会与运行平台息息相关,同时也会加入自己的各种各种限制、约束、约定、魔术方法等。所以形象来说,前者是JS国度的普通话,而后者则是方言。
业务逻辑直观,UI逻辑隐晦:UI渲染本身就是一件很复杂的事情,其间涉及到各种组件的各种生命周期、创建、销毁、更新、重绘等等、在加上各种优化手段造成的心智负担。所以你会发现某些业务逻辑放在
Redux或是Vuex等纯状态管理框架中,比使用组件内部的Hooks去维护更简单和直观。尽管Hooks也可以模拟这些Flux框架,但是不及前者有条理,比如测试、监控、分析、回滚一个Action多容易,你测试、监控、分析、回滚一个Hooks试试...业务逻辑稳定、UI逻辑多变:UI/UE太感性、太灵活了,带有很强的个人主观色彩,经常会被优化、修改、甚至推翻,不像业务逻辑那么稳定。这也是要将UI逻辑和业务逻辑分开的重要原因,如果你将业务逻辑和UI逻辑写在一起,你本来稳定的代码将受到不稳定代码的严重骚挠。
铁打的MV流水的C
现在提MVC是不是过时了?非也,MVC是其实一种最简单的哲学思想,Model代表抽象事物,View代表具体事物,而Controller则是代表如何在抽象事物和具体事物之间泛化。所以MVC是一种思想,而不是特指某种框架,过时的只会是框架,而非思想。
近年来各种演化如:MVP、MVVM、MVI等等,其实都是在围绕C做文章,最终的目的无非就是更好的隔离M和V,也就是千方百计分离UI逻辑和业务逻辑。
Flux架构其实也是一种MVC,而Redux/Vuex/Pinia、以及本人的框架Elux,都可以看作它的变种。下面我们就看看如何利用Flux架构来分离UI逻辑与业务逻辑:
从State到Model
MVVM应用中充斥着状态,有的用来描述Component的内部状况,它与Component唇齿相依,跟随Component诞生和销毁,这就是我们常说的ComponentState。
还有一些状态,用来描述业务状态,与具体哪个Component没有直接关系,不存在复用与销毁,我们可以称它为Model。
- ComponentState 是UI逻辑,应当封装在Component里面,外界也无需知道。
- Model 是业务逻辑,反映整个APP的状况,与Component无关,应当由Flux框架来统一管理。
从Event到Action
用户通过UI界面产生的人机交互事件,我们习惯叫"Event事件",而"Event事件"背后的业务目的我们可以叫"Action动作",它们一个是因一个是果,一个是表一个本。
- 处理 Event 的 Handler 是UI逻辑,应当写在UI组件中
- 处理 Action 的 Handler 是业务逻辑,应当写在Controller里面
举个具体的例子吧:"SubmitLoginForm|提交登录表单",通常要完成如下逻辑:
- 验证输入是否有效
- 验证当前用户是否已经登录
- 请求后端API,并等待返回
- 如果成功,保存用户信息,并跳回原页面
- 如果失败,提示错误,并留在原地
这是一个业务动作,因为它可以不依赖哪个具体UI而运行,用户可能通过“onClick事件”点击登录按钮来触发,也可能通过“onKeyPress”按下回车键来触发,甚至你可以直接让用户通过“Login命令”来触发。
所以“onSubmitLoginForm()”应当写在Controller而非UI组件中。
UI组件中只有"onLoginButtonClick()"或"onEnterKeyPress()",而它们往往也就一句话,就是Dispatch一个Action来触发Controller中的“onSubmitLoginForm()”
将业务逻辑移出UI组件,这样UI层就变薄了,回归到了它的本质:只负责收集业务动作,不负责处理它。
改良Flux框架
传统的Flux框架也有痛点:
- 全局中心化管理导致逻辑过于集中;
- 单实例、不销毁容易造成信息累积爆炸;
- DispatchAction机制过于简单,不适合处理前因后果的长流程业务。
Elux正是针对以上痛点进行了改良:
- 虽然坚持全局中心化管理,但Elux提出“微模块”的概念,将应用拆分成独立自治的一个个“微模块”,每个微模块仅处理自己领域内的事情。
- 不再单实例,每次路由变化都会产生一个新的空白Store,然后重新挑选有用的状态挂载,类似一种垃圾回收机制。
- 提出了ActionBus的概念,让Action作为Model中的事件来广播。
- 让Action的处理链条具备“协程”机制,更好的协同各业务动作之间的关联。
Elux践行的分层而治
正是因为遵循了轻UI、重Model的设计思想,让Elux可以挂接React/Vue等各种不同的UI框架,它们已经变得没那么重要了。
正式因为分离了UI逻辑和业务逻辑,让Elux可以用一种工程模式开发Web(浏览器)、Micro(微前端)、SSR(服务器渲染)、MP(小程序)、APP(手机应用)。
此致!欢迎交流:https://eluxjs.com
前端架构-分层而治,铁打的MV流水的C的更多相关文章
- python与excel的关系;铁打的python流水的excel
现在很多行业,都离不开用Excel: 做财务的,要用Excel做报表:做物流的,会用Excel来跟踪订单情况:做HR的,会用Excel算工资:做分析的,会用Excel计算数据做报表.不知道你有没有这样 ...
- 基于AngularJS的企业软件前端架构[转载]
这篇是我参加QCon北京2014的演讲内容: 提纲: 企业应用在软件行业中占有很大的比重,而这类软件多数现在也都采用B/S的模式开发,在这个日新月异的时代,它们的前端开发技术找到了什么改进点呢? B/ ...
- (系统架构)标准Web系统的架构分层
标准Web系统的架构分层 1.架构体系分层图 在上图中我们描述了Web系统架构中的组成部分.并且给出了每一层常用的技术组件/服务实现.需要注意以下几点: 系统架构是灵活的,根据需求的不同,不一定每一层 ...
- 用“MEAN”技术栈开发web应用(一)AngularJs前端架构
前言 不知何时突然冒出“MEAN技术栈”这个新词,听起来很牛逼的样子,其实就是我们已经熟悉了的近两年在前端比较流行的技术,mongodb.express.angularjs.nodejs,由于这几项技 ...
- 标准Web系统的架构分层
标准Web系统的架构分层 – 转载请注明出处 1.架构体系分层图 在上图中我们描述了Web系统架构中的组成部分.并且给出了每一层常用的技术组件/服务实现.需要注意以下几点: 系统架构是灵活的,根据需求 ...
- 标准Web系统的架构分层[转]
标准Web系统的架构分层 – 转载请注明出处 1.架构体系分层图 在上图中我们描述了Web系统架构中的组成部分.并且给出了每一层常用的技术组件/服务实现.需要注意以下几点: 系统架构是灵活的,根据需求 ...
- 标准web架构分层
标准Web系统的架构分层 转载:http://blog.csdn.net/yinwenjie http://blog.csdn.net/yinwenjie/article/details/464 ...
- web富客户端应用下,前端架构、系列(二)。
序 我们在上面的文章中已经建立起来一个比较简单的 前端架构 虽然这个看上去很简陋. 不过毕竟也是思想的结晶. 从这一篇文章开始,我将陆续完善这一个前端架构.. 重新构思 上一篇我们把前端架构分为3个模 ...
- <转>企业应用架构 --- 分层
系统架构师-基础到企业应用架构-分层[上篇] 一.前言 大家好,接近一年的时间没有怎么书写博客了,一方面是工作上比较忙,同时生活上也步入正轨,事情比较繁多,目前总算是趋于稳定,可以有时间来完善以前没有 ...
随机推荐
- DataX异构数据源离线同步工具json文件配置说明
DataX 是阿里开源的一个异构数据源离线同步工具,致力于实现包括关系型数据库(MySQL.Oracle等).HDFS.Hive.ODPS.HBase.FTP等各种异构数据源之间稳定高效的数据同步功能 ...
- Oracle账户被锁(the account is locked)
问题: 安装好Oracle之后用scott登录报错:ERROR:ORA-28000:the account is locked 解决方案: Win+R打开命令行输入:sqlplus 使用system账 ...
- 1.3 操作系统的第三个功能——存储管理功能 -《zobolの操作系统学习札记》
1.3 操作系统的第三个功能--存储管理功能 作者zobol:关于操作系统概论-存储管理功能,我给出下列问题: 目录 1.3 操作系统的第三个功能--存储管理功能 问1:操作系统的文件管理系统主要是负 ...
- 六张图详解LinkedList 源码解析
LinkedList 底层基于链表实现,增删不需要移动数据,所以效率很高.但是查询和修改数据的效率低,不能像数组那样根据下标快速的定位到数据,需要一个一个遍历数据. 基本结构 LinkedList 是 ...
- 一篇文章带你深入浅出Vuex
在写Vuex之前,我们先用一个简单的例子来实现一个小demo 大家都知道Vue的父传子用在很多场景,比如像这样: 父组件: <template> <div id="app& ...
- AspNetCore&云效Flow持续集成
如今有了越来越多的持续集成工具,给的个人开发者的福利也是很足了,如无必要,自建工具有时只是作为练手了. 众多持续集成工具 现在可用的持续集成工具繁多,各大云服务商都推出了持续集成,甚至是一定条件内都是 ...
- kali 漏洞扫描
前言 漏洞扫描器是一种能够自动在计算机.信息系统.网络及应用软件中寻找和发现安全弱点的程序.它通过网络对目录系统进行探测,向目标系统发送数据,并将反馈数据与自带的漏洞特征库进行匹配,进而列举目标系统上 ...
- 使用强大的DBPack处理分布式事务(PHP使用教程)
主流的分布式事务的处理方案 近些年,随着微服务的广泛使用,业务对系统的分布式事务处理能力的要求越来越高. 早期的基于XA协议的二阶段提交方案,将分布式事务的处理放在数据库驱动层,实现了对业务的无侵入, ...
- 开发人员要学的Docker从入门到日常命令使用(通俗易懂),专业运维人员请勿点!
一.介绍Docker 1.引言 问题1:开发人员告诉测试说自己的项目已经做好了,给你一个发布包,你去测试吧. ## 测试人员,为什么我运行会报错? ## 开发人员说,我本地运行没有问题呀! 解答 ...
- 数组容器(ArrayList)设计与Java实现,看完这个你不懂ArrayList,你找我!!!
数组容器(ArrayList)设计与Java实现 本篇文章主要跟大家介绍我们最常使用的一种容器ArrayList.Vector的原理,并且自己使用Java实现自己的数组容器MyArrayList,让自 ...