V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
ScottHU
V2EX  ›  程序员

(深度分析)开源框架/库的伟大与罪恶

  •  
  •   ScottHU · 2023-07-30 16:16:42 +08:00 · 3572 次点击
    这是一个创建于 474 天前的主题,其中的信息可能已经有所发展或是发生改变。

    前段我发了一篇《是时候该换掉你的 axios 了》的文章引起了热议,各位小伙伴也给出了自己的看法,本来只是随便一发的对比 axios 和 alova 优劣势的文章,但是却遭到了一些同学的质疑。

    思想碰撞是我们进步的阶梯,我没有要贬低这些质疑的意思,相反,我要感谢他们(质疑者)推着我思考和前进,在这边我想对这些声音做出自己回应。

    因为我从这些质疑声中看到了,很多人的代码思维都还停留在使用层面,而缺少更深度的理解和思考,这篇文章我想聊聊我对开源框架和库更深入的观点,从更深入的角度聊聊我为什么看好 alova !!!

    看完我保证你一定会有所收获的,没有的话你尽管喷。 还不知道 alova 的可以预先了解下:

    alova 的 Github 地址

    alova 官网

    如果你不知道 axios 的话,直通车在这

    本文主要讨论编程背后的东西,而不是某个技术点的解决方案,欢迎大家参与共同讨论!

    省流目录

    1. react 和 vue 的伟大
    2. (解答各位的质疑) alova 的优势在究竟哪里
    3. (升华)开源框架罪恶史

    react 和 vue 的伟大

    深有体会的是,开源框架和库已经实实在在地给我们带来了太多便利,在深入讨论 alova 前,我们先从来 react 和 vue 等大家最熟悉的 UI 框架说起。

    这些 UI 框架究竟给我们带来了什么,过去的王者 jquery 可谓雄霸天下,jquery 所解决的问题是提供一种更简单兼容性更好的 dom 操作 api ,让大家不需要关注兼容性问题,但对于新手来说,照样会把全部代码写在一个 js 文件中然后把代码乱放,来欣赏一段意大利泡面一样的 jquery 代码:

    // ❌整个页面的 js 处理都集中在这里了
    (function(win) {
        // 处理页头按钮点击事件
        $('#header .button').click(function() {
            // ...
        });
    
        // 处理页脚某个 tag 的鼠标移入事件
        $('#footer .tag').mouseenter(function() {
            // ...
        });
    
        // 处理主界面轮播图的事件
        $('#swiper .btn-left').mouseenter(function() {
            // ...
        });
        $('#swiper .btn-right').mouseenter(function() {
            // ...
        });
    })(window);
    

    项目以 html 、js 、css 为大模块进去分开,结构大概是这样的

    WechatIMG684.jpeg

    一团扭来扭去还弯弯曲曲的代码,可维护性直降负分,谁愿意接盘谁倒霉,随着项目逐渐复杂,每改动一处都像是一锤子锤在接盘侠的胸口上 —— 痛苦无比,只要团队里有新手,不管技术 leader 怎么制定模块拆分的规范都无法避免这种事的发生,最终接盘侠们也抛了盘……

    为什么呢?

    因为 leader 的规范只是写在文档上的意见型规范,你可以不遵守也能让项目跑起来。而 react 和 vue 等 MVVM UI 框架(以下简称 UI 框架)的优势就立即凸显出来了,这让它们很快把过去的王者 jquery 击败了,这些 UI 框架的最伟大之处就在于,它们提供了一种可维护性更高的代码组织模式 —— 组件化,并强制大家都使用这种方式来开发应用。组件化中,html 、js 、css 以组件为最小单元聚合,组件之间相互解耦,大概是这样的

    WechatIMG683.jpeg

    它们形成了一种制约型规范,不遵守项目就无法跑起来,这种方式让天底下的前端开发者达成了统一的模块化共识,就像你家的电源插槽那样统一。

    我觉得以上就是框架和库的区别!!!

    这种制约型规范才能让组件库百花齐放,各种组件库开始诞生进一步为大家减少开发量。

    这就是制约型规范的威力,可能你突然就懂了为什么要用 husky 了。

    而使用数据驱动视图的 MVVM 模式,虽然相比于 jq 也是降维打击的存在,但我觉得它的重要性并没有组件化伟大。

    (重要)制定规范的目的除了规范变量名和注释外,更重要的是在代码组织层面实现高聚合、低耦合, 不陌生吧,而且我觉得 vue 的 SCF 、指令相比 react 的 jsx 又进一步做到了强制型规范。

    (解答各位的质疑) alova 的优势在究竟哪里

    如果你理解了上面的规范问题,我们再接着聊相比于react-queryswrvueuse 的 useFetch以及ahook 的 useRequest等,alova 有什么特别之处?我很认同作者在《是时候该换掉你的 axios 了》中的评论:

    1.png

    在得知我还要再发一篇深度解析文后,在周一晚上,作者找到了我,聊了 3 个小时,他表达了不希望 alova 被我带偏了,那次聊过后也体会到了作者的思想,大概如下:

    js 库可以分为规范型 js 库和功能型 js 库

    规范型 js 库

    像 react 和 vue 等 UI 框架除了提供 api 外,还提供了组件化(制约型规范),很显然是规范型的库,即框架。

    功能型 js 库

    如 axios 、moment 、lodash 、jquery 等都是属于功能型 js 库,它们更多的价值是提供便于调用的 api ,而 react-query 和 swr 等确实是使用 use hook 管理请求以及使用请求缓存的先驱者,但好像除了这些再没有规范层面的影子,因此更倾向于把它们归类到功能型 js 库中,贴上示例。

    react-query 官方示例简析

    function Example() {
      // 在每次 useQuery 中调用 fetch 或 axios 发送请求,耦合度较高
      // 需手动维护 queryKey
      const { isLoading, error, data } = useQuery({
        queryKey: ['repoData'],
        queryFn: () =>
          fetch('https://api.github.com/repos/tannerlinsley/react-query').then(
            (res) => res.json(),
          ),
      })
    
      if (isLoading) return 'Loading...'
      if (error) return 'An error has occurred: ' + error.message
      return (
        <div>
          <h1>{data.name}</h1>
          <p>{data.description}</p>
          <strong>👀 {data.subscribers_count}</strong>{' '}
          <strong>✨ {data.stargazers_count}</strong>{' '}
          <strong>🍴 {data.forks_count}</strong>
        </div>
      )
    }
    

    swr 官方示例简析

    // 耦合的方式请求
    const fetcher = url => fetch(url).then(r => r.json())
    function App () {
      const { data, error } = useSWR('/api/data', fetcher)
      // ...
    }
    
    // 解耦的方式
    import useSWR, { SWRConfig } from 'swr'
    function Dashboard () {
      const { data: events } = useSWR('/api/events')
      const { data: projects } = useSWR('/api/projects')
      const { data: user } = useSWR('/api/user', { refreshInterval: 0 }) // override
      // ...
    }
     
    function App () {
      return (
        <SWRConfig
          value={{
            refreshInterval: 3000,
            fetcher: (resource, init) => fetch(resource, init).then(res => res.json())
          }}
        >
          <Dashboard />
        </SWRConfig>
      )
    }
    

    我觉得 vercel 团队是有思考到这点的,只是把解耦的方式作为了一个可选项。

    alova 的不同之处

    虽然 alova 相比于 axios 、react query 、swr 等前辈大咖,alova 只能算是新秀中的新秀,其他库已经发展了 5 到 10 年了,作者好像也比较低调。但在我看来 alova 在解决思想上和前辈们相比会更加深入,也更加彻底。

    alova 的作者提出了一个叫 RSM 规范(请求场景模型) 的模型,并让 alova 遵循这个模型来设计,官方示例代码如下:

    import { createAlova } from 'alova';
    import GlobalFetch from 'alova/GlobalFetch';
    import VueHook from 'alova/vue';
    
    const alovaInstance = createAlova({
        // 假设我们需要与这个域名的服务器交互
        baseURL: 'https://api.alovajs.org',
    
        // VueHook 可以帮我们用 vue 的 ref 函数创建请求相关的,可以被 Alova 管理的状态
        statesHook: VueHook,
    
        // 请求适配器,我们推荐并提供了 fetch 请求适配器
        requestAdapter: GlobalFetch(),
        
        // 全局请求前钩子
        beforeRequest(method) {  
            // ... 
        },
        
        // 全局响应钩子
        responsed: {
            onSuccess(response, method) {
                // ...
            },
            onError(err) {
                // ...
            }
        }
    });
    
    // 创建一个 Get 实例,描述一次 Get 请求的信息
    const todoListGetter = alovaInstance.Get('/todo/list', {
        // 请求头
        headers: {
            'Content-Type': 'application/json;charset=UTF-8'
        },
        // params 参数将会以?的形式拼接在 url 后面
        params: {
            userId: 1
        },
        
        // 单独为这个请求设置缓存时间
        localCache: 50000,
        // 单独为这个请求开启请求共享
        shareRequest: true,
        // 数据转换
        transformData(result) {
            // ...
        },
        // ...
    });
    

    从以上示例中,可以看出 alova 的以下两个优势:

    1. alova 以请求适配器、存储适配器、UI 框架适配器的方式,将请求工具和请求方式进行了强制解耦,实现了低耦合,提高了代码的可移植性,而不是可选项。
    2. alova 中的 Method 概念,用于实现 RSM 的请求行为,它也强制将请求相关的信息、请求行为相关的信息高度聚合在了 Method 中,实现了高聚合。

    作者原话告诉我:alova 提供了高聚合低耦合的代码组织方式,可以更大程度地管理请求相关的代码,随着项目越来越复杂,它的优势也就会慢慢显现出来,而且在编码方面也更加统一了。同时保持了高度了灵活性,供用户提供了足够的自定义空间。

    因此,我会把 alova 放在介于规范型库和功能型库的中间位置

    最后,据官网介绍,alova 的目标是通过按业务场景来实现兼开发体验和用户体验为一体,而 alova 的高度灵活性就可以支持自定义策略,你可以封装了公司内部用,比如你的公司很喜欢用某种处理来优化性能,或者写成 alova 插件一样的自己的策略库,那 alova 刚好都可以提供支持。

    说到这边,好像 alova 的 use hook 形式显得好像没那么重要了,这个就要问作者了🙄。不懂有没有解答大家的疑问。

    (升华)开源框架罪恶史

    react 和 vue 都更关注 UI 层面,它们简化了 UI 层面的问题,但据我的理解,目前从 js 逻辑的层面却还是没有统一制约规范,或相关的 js 逻辑框架来解决这个问题,新手和高手写出的代码可维护性上还是有一定差距的。UI 框架让事情简单化的同时,也养肥了一堆躺在 UI 框架的成绩上好吃懒做的人,这些人往往会有以下两个问题:

    1. 不再思考规范问题、模块之间的界限和协作,甚至都意识不到这些东西的存在,然后不分职责、把代码到处乱写,请想象有一只狗到处乱拉……,然后堆积成的叫什么山😎。
    2. 他们只享受上层成果,不再关注底层的东西,哪怕稍微底层一点的,因为确实用不着了,就像我们不再关注垃圾回收的问题( C 语言里是需要手动回收的),更离谱的是,有些人连getElementByIdappendChildinsertBefore是干什么的,更别问他们 nodetype 有几种类型,fragment 是什么,注释是不是一种 node 等等。

    可想而知,尖端人才变少是有理由的,知道为什么高级前端难招了吧!!!当然也不乏一小部分喜欢钻研的同学,喜欢知其然知其所以然。

    这好像是时代发展、科技进步带来的无法避免的副作用,它们为我们提供了强大且便利的工具外,也在慢慢摧残着这么一大群人,和平年代不需要那么多英雄。这让我又想到了《反脆弱》里的观点 —— 现代化是这个世界的脆弱推手。

    插个题外话,毕竟 react 和 vue 接管的是 UI 层面的组件化规范,但在 js 逻辑层面的规范都还停留在文档上,还没有形成制约型规范,在这个层面新手朋友一样可以把它们写成意大利面,有兴趣的同学也可以开始思考一下了,有没有可能从 js 逻辑层面提出制约型规范,然后形成一个新的 js 框架,就像 UI 框架组件化规范一样,如果有人做到了,可否回来留言告诉我下😌😌😌

    结尾

    这篇文章并没有去解决一个具体问题,能看到这里的同学,看来都是学习和交流的同学。

    那问题来了,你们理解的代码规范是怎样的呢?

    24 条回复    2023-08-01 01:40:46 +08:00
    agagega
        1
    agagega  
       2023-07-30 16:27:11 +08:00 via iPhone
    关键字:抽象泄露。在抽象能够完美工作,不需要面对性能问题或无法实现的需求时,框架带来的技能需求下降不是好事吗?
    haolongsun
        2
    haolongsun  
       2023-07-30 16:42:33 +08:00
    过早优化是万恶之源,遇到了再去解决,没遇到之前就不去想,不然劳心费神,没办法专注当前事情。
    janus77
        3
    janus77  
       2023-07-30 16:54:42 +08:00
    看了半天,没发现前端的形容词
    haha512
        4
    haha512  
       2023-07-30 17:44:12 +08:00   ❤️ 1
    回字的第 108 种写法
    Garwih
        5
    Garwih  
       2023-07-30 18:03:22 +08:00   ❤️ 7
    一人分饰两角,有种精神分裂的美
    dw2693734d
        6
    dw2693734d  
       2023-07-30 18:08:53 +08:00 via iPhone
    phoenix 的 LiveView 也不错
    hsfzxjy
        7
    hsfzxjy  
       2023-07-30 18:20:15 +08:00   ❤️ 2
    > 可想而知,尖端人才变少是有理由的,知道为什么高级前端难招了吧

    框架的诞生降低了领域的门槛,使更多的人涌入这个领域。尖端人才的绝对数量没有减少,而是被稀释了。

    > UI 框架让事情简单化的同时,也养肥了一堆躺在 UI 框架的成绩上好吃懒做的人

    我同意你描述的这个现象,但最好不要责怪他们/框架。这其实是多数领域的普遍规律:技术的进步降低了一个领域的门槛,导致更多的人以此谋生,这从社会层面来看是好的事情。只要在领域高层的地方一直有人思考领域的前进方向,这个领域就是会良性发展的。

    ---

    > 因为我从这些质疑声中看到了,很多人的代码思维都还停留在使用层面,而缺少更深度的理解和思考

    另外,你的两篇帖子的标题都有过分扩大化的嫌疑——上一篇帖子的大多数负面评价多来源于此。我认为你将“大量质疑的出现”完全归因于“很多人缺少更深度的理解和思考”是不合适的,因为标题有很强的情绪引导效果。理性的交流还需要我们使用较为平常的表达方式。
    charlie21
        8
    charlie21  
       2023-07-30 18:40:01 +08:00 via Android
    在你的例子里提到的 vue SFC (Single-File Component ,本质上是 vue 编译器新晋支持的语法糖) 刚出时候也是受到抵制的。但后来经受住了时间的检验
    iOCZ
        9
    iOCZ  
       2023-07-30 18:40:51 +08:00   ❤️ 1
    如果人人都要精通的话,能从事这个行业的人就会变少,生产效率就会比较底下。社会化分工也存在于互联网这个行业。让不同水平的人去关注不同层面的东西这个是合理的。但总得有人去维护底层,需要掌握所有的基础知识。
    snoy
        10
    snoy  
       2023-07-30 18:42:42 +08:00
    什么开源框架目前都不如节流框架给力😄,搞一个节流框架团队人员减半😄,
    Oz37sW2w3MIZf56o
        11
    Oz37sW2w3MIZf56o  
       2023-07-30 19:06:32 +08:00
    首先开源无罪,把自己的知识成果无私奉献出来是值得称赞的;

    但是我感觉你所说的优势(低耦合),作为一个网络请求工具,是没有使用场景的;
    回忆一下我自己使用 ajax 或者 axios 的场景,通常就是只配置一次公共属性,在业务中我只需要关心请求路径、请求方法(get,post,put...)和请求参数.;
    如果我担心在文件中引入了第三方库的文件,完全可以用一个 wrapper 来处理. 至于路径、方法,参数这三者本来就是业务的一部分.要改这三者,只能是业务变了.
    lanlanye
        12
    lanlanye  
       2023-07-30 20:27:35 +08:00 via iPhone
    这个升华部分的批判毫无道理……就好像在批判 Java 这样有 GC 的语言让程序员的平均水平降低了一样……
    事实上确实降低了,但它同时降低的还有这个行业的门槛,最终的结果是提高了整个行业的生产效率,而效率才是市场真正追求的东西。
    至于顶尖人才变少,这个不知道有没有具体数据支撑?也许这些人的绝对数量并没有什么变化,给你这种感觉是因为他们占行业总人数的比例减少了。
    danhahaha
        13
    danhahaha  
       2023-07-30 20:44:25 +08:00   ❤️ 6
    啥时候能把这个捧一个打一个的丑毛病改改?
    jiangzm
        14
    jiangzm  
       2023-07-30 21:48:33 +08:00   ❤️ 1
    罪恶都来了 哈哈哈哈😂,前端的东西很多但都很简单,写框架的和写业务的区别真不大只是侧重方向不一样,没必要拉高踩低的。
    还有造这种轮子除了拿来练练手其他意义不大。 还有看了项目代码总结就是不太规范、质量不高,过度设计。
    http client 仅关心网络层就够了,不需要关心业务场景,比如缓存、分页、组件、应用层框架等。
    代码并不是多就是好,有很多前端优秀的库都是如此,简单易用是首要原则。
    molvqingtai
        15
    molvqingtai  
       2023-07-30 22:24:28 +08:00 via Android   ❤️ 1
    分析得很好,请以后不要分析了
    adoal
        16
    adoal  
       2023-07-30 23:04:18 +08:00   ❤️ 1
    前端戏精姿势多
    geligaoli
        17
    geligaoli  
       2023-07-31 07:21:27 +08:00
    凡是一旦扯上伟大与罪恶的,秒变精神小伙
    KENNHI
        18
    KENNHI  
       2023-07-31 07:53:42 +08:00 via Android
    前端弄出来这么一大堆概念库和框架,最后因为用户的设备带不动他们的“先进理念”,打开网页动不动狂吃内存风扇狂转之后又得借助 SSR 通过服务器渲染,给我整不明白了,那我为什么不用 Thymeleaf 甚至 jsp 加点类似 jQuery 的库呢。你们又不是在浏览器里实现个 office365 ,自己问问自己写的那些东西用 jQuery 是不是一样能实现?把 Model 和 Router 都还给后端吧,脚本程序在浏览器验证下表单,必要的时候用个 Ajax 差不多了,整个 web 都被你们搞得卡得要死。
    Cloudust
        19
    Cloudust  
       2023-07-31 08:43:55 +08:00
    分析的很好,不过从使用来看跟 axios 貌似没什么太大区别?没看出优势到底在哪
    zdw189803631
        20
    zdw189803631  
       2023-07-31 09:13:27 +08:00
    难道不是因为你起的标题的缘故... 这种标题见得多,谁看到都想喷一句😂
    AlexHsu
        21
    AlexHsu  
       2023-07-31 11:07:52 +08:00
    害 说白了前端需要一个巫妖王 天天维护屎的前端知道 spring 为啥又丑又大又笨 天天有新框架要干他就是干不掉了吧 因为没有这个巫妖王 行业规范化都是暂时的
    所以问题来了 前端为什么没有巫妖王 框架这么割裂
    sankooc
        22
    sankooc  
       2023-07-31 11:55:17 +08:00
    你们真觉得 react 在大部分应用场景上都有优势么? 为啥我觉得接盘 react 更痛苦
    Daming
        23
    Daming  
       2023-07-31 17:31:52 +08:00
    标题很有攻击性,让人看了就有进来喷的冲动。
    learningman
        24
    learningman  
       2023-08-01 01:40:46 +08:00 via Android
    一桶水不满,半桶水晃荡。
    啥时候进了 ecma 委员会再来高屋建瓴吧
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2885 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 31ms · UTC 06:33 · PVG 14:33 · LAX 22:33 · JFK 01:33
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.