现代前端开发框架:我们是否过于崇拜?

发表时间: 2022-11-30 18:09

前端界有两个“教派”,一个叫 Vue,一个叫 React。Vue 的成员看不起 React,React 成员鄙视 Vue,他们认为手中的“教义”就是真理,可以消灭世界一切苦难。

前端界有两个“教派”,一个叫 Vue,一个叫 React。Vue 的成员看不起 React,React 成员鄙视 Vue,他们认为手中的“教义”就是真理,可以消灭世界一切苦难。


但正如没有绝对的真理,也没有绝对完美的系统框架,我们需要一双明辨是非的眼睛去解析所面对的难题,带我们找到正确的方法,解决所面对的困难。我们需要抱着怀疑的眼光去看待现代前端开发框架,它们真的能解决我们的问题吗?答案是肯定的,也是否定的。框架并不能独立的发挥作用,其中开发者是一个很大的变量,而开发者这个最大的变量才是最终影响问题是否能够被解决的重要因素。


本文从对现代前端框架的“崇拜”现象,引出了前端开发面临的过于强调工具本身,忽视了开发者怎么写好代码才是影响代码质量的本质问题,最后给出了一种我认为可解决业务型前端项目的代码架构方案(也可以说是一种开发思想),希望能给大家带来一些思路和帮助。


一、前端开发的困境

从我的经历来看,现代前端框架的‘崇拜’导致前端开发变得更加复杂,间接导致代码质量变差,软件的生命周期变短。

当前我们所面临的困境是技术方案有的时候用的特别顺手、高效,而有的时候却很蹩脚、处处碰壁?有的人用着轻松欢快,而有的人用着烦躁不已?有的项目引入了新工具开发效率一下子就上去了,有的项目反而变得越来越复杂难以迭代?


究其原因是因为我们一直在追求一种足够简单、足够高效、足够快、足够应对复杂变化的业务场景的完美的技术方案。这已经成为了一种前端界的主流意识,每一种新框架、工具的出现都打着比前者更出众,更牛的口号,给我们一种感觉,好像用了它,那么一切问题就迎刃而解。但这样的“神器”真的有吗?我是持怀疑态度的,软件开发是一个复杂的系统过程,这是一个开放式的问题,想用一种 “封闭式” 的方案来解决这个问题是违背真理的。


现代前端开发框架就面临着这个问题,我们有点 “小题大作” 了,妄想用框架来解决一切问题忽略其本质解决的是视图层渲染的问题。随着 React/Vue 等数据驱动 UI 框架的流行,它好像成为了我们手中的一个 “神器”,好像用它可以解决开发中的一切问题。而事实上也是这样的,如果发现有的问题没有解决好,那么就围绕着这些框架扩展新工具就好,所有我们有了 React 全家桶、有了 Vue 全家桶。这样还不够,我们还有众多的工具库可自由组合使用,分不清的数据状态管理库、多种路由跳转方案、丰富的组件集合、各种开发调试工具、二次封装的全栈框架等。看似情况越来越好,一切欣欣向荣,幸福的彼岸就在眼前。事实是我们的开发者一直在负重前行,我们的系统变得很复杂(复杂到个人乃至一个团队都没法去掌控),我们不敢想五年后是否还能运行起来?


工具可以带来提效,可以让工作变得更精细,但影响成品质量的至关重要因素是使用的方式而不是工具本身。对于前端框架,我们要认识到其本身是用来解决视图层问题的,当我们妄想用框架来解决所有问题的时候,就已经走进了误区,忽略了本质问题。


二、这是“现代前端开发框架”的锅?

前文我表达了“从我的经历来看,现代前端框架的‘崇拜’导致前端开发变得更加复杂,间接导致代码质量变差,软件的生命周期变短。” 这里并不是说是现代前端框架造成了这一系列的问题,事实上我非常认可前端框架给前端开发带来的变革,它解决了我们开发界面过程中繁琐的 DOM 操作问题;带来了便捷的组件式的代码复用共享机制;这是一种正向的技术进步。问题的本质是社区带来的 “崇拜” 文化,这是运行机制带来的问题,前端框架只是其中某个重要的节点,我们不能因为工具没有使用好就怪工具本身。


1. 为什么好的东西会变“坏”?

有一个比较普适的做事原则是 “小事做大,大事做小”。而在前端框架这一块犯了一个错误,过于强调 “小事做大”,也可以说是 “小题大作” 了,大和小是相对的,我们现在妄想用 React/Vue 这一套方案解决整个前端开发的问题,这就是好的东西会变 “坏” 的原因。


我在比较早期的时候就接触了 React/Vue 这一类的框架,老实说当时是很惊艳的,那时的它们有很明确的定位和解决问题的边界,它们是很纯粹的视图层工具库(那时还没有提到框架的概念),简洁优雅。但随着它们的不断迭代和社区的推波助澜,逐渐的走向了一条不确定的道路,越来越多的衍生工具,越来越多的概念。我承认这些东西有其优秀的地方,但好的东西并不是万能的东西,需要适合的方法用在合适的地方,否则就变成了“恶”。


2. 框架的快速发展和开发人员缓慢吸收矛盾

软件开发是一个复杂的系统构建过程,这里开发人员永远是最大的变量,前端界面对的问题就是技术方案短时间内的急速发展,1% 的创造者理论提出者,10% 的参与人员将方案推向市场,而大部分的开发者处于一个被动接受和使用的角度。这个过程会导致方案推广出现信息丢失、带来误差、引出变种方案。同时也可能会给于框架维护者带来负向的反馈,带来缺陷。


技术 “宗教” 或者说过于对某一项技术的 “崇拜” 会加速新技术推向市场的过程,推广的过程中会出现曲解、模糊。这其中有的是无意的,有的则是故意的。这些在现代前端框架中就出现了,因为这个不健康的成长现象导致了框架的使用被推到极端,而开发者们很可能还没有建立起敏锐的技术敏感度和判断能力,导致出现整个前端看似蓬勃发展,但大家却痛苦不堪的现象。


三、破除困境的方法?

1. 好的东西可能会变 “坏”,坏的东西也可能会变 “好”

好心可能会办坏事,坏事也可能带来出乎意料的好处。这其中发挥作用的因素之一就是做事的人这个大 “变量”。为了让事情办好,我们需要培养起一个技术能力高的团队,开发者们都有意识的去关注代码质量,关心技术架构,思考写出更好的代码。这是一个最原始最有效的办法,当然这也是最难,成本最高的方案。


2. 建立拥有正向反馈能力的运行机制?

机制是一个很强大的东西,甚至能弥补影响因素带来的负面问题。对于一个复杂系统来说,机制的作用是要大于单个因素的,机制可以调节单个因素造成的误差,但单个因素却很难影响整个运行机制。
怎么建立良好的运行机制我还没有思考出好的办法,有想法的同学可以一起交流。虽然还没有找到建立的方式,但我认为这是一条正确的路,值得去探索。


3. 有效训练,代码是“写”出来的?

做为一个开发者,我发现有两件事情基本上每天都会做,一不停地写代码、二是持续性的学习。按理来说,每天都在写代码,按照一万小时定律,我们的编码水平应该会不断提升才对,但现实是好像有一条边界,当我达到那条边界后就停滞不前。


有变化的持续性行为才可能会出现由量变到质变的突破,长期的无效练习不然短期的有效训练。


看了许多书籍、文章,听了很多分享、讲座,评了很多方案,用了很多新技术。但都会有一种浅尝辄止的感觉,难道勤学不能带来成长?

  • 再多的信息也不等于知识,经由我们自己的思维转换并以自己的理解方式吸收的才是自己的知识,将知识应用结合到日常工作中的才算是个人的能力
  • 人的思考能力是有限的,而现实现象是一个复杂多维度的系统,远超个人所能掌控的极限。正确的做法应该是由小到大,深入挖掘单个维度的现象,最后通过有序的方式组合起来就是一个复杂多维度的系统。


四、我们需要合适的代码架构方案?

我设计过许多底层框架工具,如果要说其中最困难的地方在哪,那就是框架设计者必须考虑到框架本身和使用的开发者间的对立关系(框架和开发者是一个资源争夺的关系,他们争夺的是软件中的计算量,或者简单的说是代码量)。处理好这种关系,让它达到一个动态平衡的过程是设计者要解决的本质问题。

这里我将介绍一种架构方案,该方案在前端框架的基础上进行了延伸,有效的解决了业务型(业务逻辑比较重)前端类需求的复杂度问题。


该方案目前还是理论设计和验证阶段,还没有在真实业务中落地,大家可以带着辩证的眼光来看待。
若认可该方案,可以互相交流;若不喜,请勿喷我。


三是一个很好的数字,我认为一个架构方案能够解决好三个系统性问题就可以算是一个优秀的方案,而这里介绍的方案则围绕如下三个原则而来。

  • 分层
  • 组合
  • 单向依赖


在大的层面借助分层的思想将事情分类隔离开,每一层直接通过接口联结工作,降低整个系统的复杂度。比如客户端就不用关心后端接口的具体实现,只要接口如预期工作就好。


在每一层的实现中则可以通过模块组合的形式最终得到完整的功能。因为前端具有高频变化的特性,所以更建议使用组合而不是面向对象继承的方式来组织代码逻辑,继承的模式应该更适用于稳固的结构。

分层分模块之后,需要通过线连接起来才能得到一个完整的应用,单向依赖可以避免得到一个无序的网状结构导致逻辑难以理顺。

在思考上面提到的三个原则的过程中,我发现现存的 MVP 架构模型就很好的做到了,基于 MVP 架构做一点优化就得到了我认为好的一种架构设计。关键的问题还是我们怎么和自己的开发思维、业务特性结合起来的问题。

除了架构原则方面,我们再分析一下代码编写本质的东西,什么原因会导致代码质量变差?以及如何去解决?


1. 什么原因会导致前端代码变差?

前端开发中一个比较核心的问题是视图的开发,这个问题被框架有效的解决了,当不用去直接操作 DOM 后,开发体验得到了极大的提高。但存在的问题或者说带来的一个误导是视图的开发就是全部,所以我们变成了组件式编程,带来的后果就是所有的代码联系过于紧密。


我认为以视图为中心的代码组织模式会随着迭代的进行导致代码越来越混乱,而且逻辑代码与视图层耦合会导致所有的代码如同一碗面条一样杂乱不开。

  • 视图是变化频率比较高的,以视图为中心的代码组织方式就如同以视图作为房子的底座去建房,导致的结果就是每次视图变化了你就需要费很大的劲去调整房子的其它部件以适应底座的变化,所谓牵一发而动全身正是如此。
  • 以视图作为代码主体还有一个问题就是视图不能完整的反应业务需求,有部分的业务逻辑是与视图无关的。随着业务逻辑的比重越大就会出现头重脚轻的现象。
  • 数据状态管理工具可以解决业务逻辑变重的问题吗?我认为是否定的,数据状态管理工具并没有脱离视图框架的本质,只是将组件内的局部状态管理模式转换为了全局状态管理的模式。类似于有了一个中心的仓库放置闲置的物品,并不会降低管理物品的难度,关键的地方应该在于一套科学合理的闲置物品分类管理方案,将杂乱无章的巨型仓库变成物美一样的大型超市


基于上述分析,我认为的一个解决之道就是要将视图层独立出来,视图与逻辑隔离,实现动静分离。


2. 前端的主要关注点是什么?

前面说了以视图为中心的前端代码组织方式存在弊端,那么好的方式应该是什么呢?回归业务的本质,以业务为中心,视图只是业务流程的界面表现方式。UI 是一个单纯的东西,我觉得不能算是业务逻辑,前端中的业务逻辑应该是业务流程与界面的联结表现,这里有一个主辅的区别。


做为前端的你是否也曾有过疑问,有时候前后端的边界不是很清晰,有的功能可以端上做,也可以在服务端做。客户端和服务端的对立也影响着客户端技术的发展,从而保留着服务端的影子。


思考一个问题,如果前端摒除了视图部分,那么前后端的代码还会有什么区别呢?这么想着将后端那一套长期稳定的架构带到前端也不是不可能。MVC/MVP 架构是在后端开发中比较成熟的方案,我认为应用到前端也是可行的, 关键是要和前端现有的技术方案结合起来。


3. React Hook/Vue Composition API 带来的开发思维转变?

React Hook 不仅仅是对 Class 组件的替代,Vue Composition API 也不仅仅是 Options API 的语法升级,我觉得是更本质的编程思维上的改变。
以如下的 swr 示例代码为例:

function useUser(id) {  const { data, error } = useSWR(`/api/user/${id}`, fetcher)  return {    user: data,    isLoading: !error && !data,    isError: error,  }}


从上面我们可以看到 useSWR的引入就如同引入一个普通的 util函数一样,这里考虑的不是组件初始化的时候做什么?组件刷新的时候做什么?而是纯粹的思考数据的变化流程,即变成计算的问题。这其实也是一种视图与逻辑层分离的思想,将业务逻辑聚焦到了 useSWRhook 中(包含了请求、加载中间态、错误太的处理)。但可惜的是目前 hook 并不完美,还存在如不可在条件式语句中使用、重复渲染的问题。Vue Composition API 的目前也还没有成为主流方式,一切都还在摸索中。社区上已经有众多基于此的数据状态更新方案,我相信,未来会出现更多基于此的前端代码架构方案。


点击查看原文,获取更多福利!

https://developer.aliyun.com/article/1095810?utm_content=g_1000365537


版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。