当前位置: 首页 > Web前端 > HTML

前端数据建模指南

时间:2023-04-02 22:19:46 HTML

什么是前端数据建模?说到数据建模,大多数人首先想到的是后端和数据相关的内容。前端数据建模看起来很奇怪。那么我将通过回答以下问题来统一我们对前端数据建模概念的理解。什么是数据建模?数据建模是分析和定义业务逻辑使用的数据以及这些数据之间的关系的过程。数据建模的重点是什么?为团队成员之间的协作创建统一模型。通过定义数据需求和使用来识别改进业务流程的机会。节省代码维护成本。减少错误并提高数据完整性。前端需要数据建模吗?在我的理念中,前端应该始终关注用户体验。但实际上,前端并不能完全脱离业务逻辑。既然涉及到业务,就应该建立模型。前端数据建模的优缺点是什么?研发阶段:定义数据和关系需要时间和精力。维护阶段:节省逻辑变更后的修改时间,保持页面相对稳定。综上所述,在业务逻辑比较复杂的系统中,前端数据建模是很有必要的。在一些临时项目中,数据建模不是必需的。页面和模型数据建模就是围绕数据建立模型。在大多数前端开发者眼中,业务内容通常是以页面(Page)为纬度来切分的。而不是以模型(Model)为纬度裁剪业务内容。这会导致一个问题,前端很难自己形成一个内聚的系统。所有与页面功能相关的内容都将存储在该页面中。如果其他页面需要依赖本页面的某些数据或某些功能,很多人会选择复制一段相应的代码来完成功能。因为这种做法接近于人类的原始本能——“拒绝思考”。稍有追求的人会将多个页面会共享的数据和功能抽离到一个单独的位置,然后分别被这两个页面引用。这称为“封装”。但是这种封装是不符合逻辑的,只是遵循“多个页面在一个页面中引用某个相同的功能,所以必须将这个功能抽取出来封装成一个独立的功能”。这种方法没有错。但是,做的程度还是不够。比如在开发阶段,页面A、B、C都依赖函数FuncX,所以你把FuncX包装起来。但是后来业务逻辑变了,PageA、B、Page的逻辑C需要处理的是不同的。这时候你要么在PageC中去掉所有对FuncX的依赖,在PageC中写自己的逻辑。或者在FuncX中加入一个判断代码来区分PageC和PageA、B,然后调用不同的逻辑。无论哪种方式,都不容易维护代码。因为你的系统是完全不稳定和易变的。为什么会这样?这是因为缺少模型。从目前的技术角度来看,一个前端页面可以拆分成几个部分:UI、路由、界面、数据和业务逻辑。其中,UI是纯前端层面的东西,通过组件化或者CSS实现复用。路由是页面的一部分,不能重复使用。剩下的接口、数据和业务逻辑可以在一定程度上复用。模型主要由数据和业务逻辑组成。数据建模应该做什么?目录结构划分一个好的目录结构应该是高内聚低耦合的。很多人喜欢按照技术职责来划分文件夹,如下:这不是我推荐的做法。我认为一个高度内聚的目录结构应该按照模块来区分,如下:文件夹层次结构应该尽可能扁平,不要太深。定义接口定义接口的过程基本上就是定义数据模型的过程。因为接口是稳定的而实现是可变的。实现一个业务功能,任何一个程序员都可以做到,没有门槛。真正的难点在于如何抽象业务逻辑并将其定义为接口。有一定的门槛。以购物车场景为例。购物车的数据分为以下几个部分:商品排序条件。项目过滤器。图为状态。项目列表加载状态。购物车项目列表加载状态。产品列表。购物车项目列表。项目总数。商品的总价。更改购物车数据的方式有以下操作:初始化购物车。将商品添加到购物车。从购物车中移除商品。添加商品。减少商品。提交您的订单。根据上面的文字定义,我们可以使用TypeScript来定义一个接口。接口IGoodscartModel{过滤器:过滤器;命令:字符串;imageVisible:布尔值;商品清单:商品清单;购物车清单:购物车清单;总计:()=>数字;数量:()=>数量;initialGoodsList:()=>Promise;initialGoodscart:()=>Promise;addToCart:(goodsId:string)=>void;plusGoods:(goodsId:string)=>void;minusGoods:(goodsId:string)=>void;removeGoods:(goodsId:string)=>void;submitOrder:()=>Promise;}一旦定义了这个接口,实现就无关紧要了。因为业务逻辑的细节,只要思维正常,逻辑能力强的人都能写出来。对于逻辑来说,接口就像一个蓝图。有了这份图纸,就算是最贱的苦力,也能建造出琼楼玉宇。当然,这里面还有一些细节。比如购物车中商品的总数量和购物车中商品的总价是通过计算得到的,属于计算属性,所以在模型的定义中,定义为函数而不是一个基本类型。比如初始化商品列表和购物车商品列表是一个异步操作,所以定义为一个返回Promise的函数。你可能会发现,这不就是面向对象编程中的知识吗?没错,这就是面向对象的封装、继承、多态和组合。区分数据的性质虽然在上面的模型中定义了很多数据字段,但并不是所有的数据都一定属于模型。有一些临时数据应该存储在页面中。区分数据性质的方法有很多种,但我认为对于前端来说不需要过于复杂,只需要根据一个条件来区分——数据从哪里来?因此,可以区分系统外部数据和系统内部数据。由于Web应用的特殊性,基本上所有的Web应用都依赖于系统的外部数据。这些数据通常由接口提供。本系统外部数据相对稳定、纯净。系统内部数据可以根据业务的重要性分为多种类型。例如,存储在内存中的值可以称为临时值。当页面刷新时,这些值会被重置。重置值通常来自两个位置,一个是存储在本地存储(WebStorage)中的值,可以称为缓存值。另一种是代码中写的值,可以称为默认值。这几类数据之间存在着流动关系,这意味着不同属性的值会在系统运行的不同阶段相互转换。比如页面加载时,首先调用接口获取系统的外部数据。获取成功后,将系统外部数据转化为临时值。用户修改临时值后,对数据进行某种提交操作,将临时值同步到系统。外部的。某些用户操作也可以在本地缓存中存储临时值,成为缓存值。当用户离开网站并再次返回时,缓存值将被读取并替换为临时值。归纳起来,数据的类型分为以下几类:系统外部数据(通常来自接口)系统内部数据默认值(通常硬编码在代码中)临时值(通常存储在内存中)缓存值(通常存储在本地缓存中)这几类数据可以相互同步转换。根据上面的分类,我们可以发现排序、过滤、图片显示和隐藏状态应该属于页面,而不是模块。因为这些数据的功能是和页面强绑定的,或者说,这些功能本身就是属于页面的,不应该拆分成模块。结合框架实现数据响应式数据模型的定义与框架无关。但是我们通常需要配合数据响应性来实现操作数据自动更新UI的功能。否则,你需要在模型中处理UI变化,这会导致模型依赖于UI,这不是我们想要的。目前主流的UI框架都是对数据响应的。但我建议结合一些状态管理库。前面说了,只有比较大的项目才会用到数据建模。在规模比较大的项目中,使用状态管理库可以让我们的开发更加高效。下面是一个使用pinia的代码示例:import{defineStore}from"pinia";从“./model”导入{GoodscartModel};constgoodscart=newGoodscartModel();const{goodsList,goodsListList,goodsListLoading,total,quantity,initialGoodsList,plusGoods,minusGoods,addToCart,removeGoods,order,}=goodscart;exportconstuseGoodscartStore=defineStore("goodscart",{state(){返回{goodscartList,goodsList,goodsListLoading,};},actions:{initialGoodsList,plusGoods,addToCart,removeGoods,order,},getters:{total,quantity,},});增加接口的防腐层定义模型,对于前端来说还有另外一层意义。可以起到隔离内外连接,提高系统稳定性的作用。我们把前端想象成一个系统。系统中有很多外部资源,比如图片、视频、字体、图标、样式、脚本等等,还有很重要的接口。一般情况下,在开发过程中,界面中的字段名、字段类型、数据结构是非常易变的,尤其是遇到追求代码的非专业或底层后端人员时,对接的界面会很烦人和痛苦的事情。从根本上说,造成这种现象的原因是界面的变化不在我们的控制范围之内,它是系统之外不可控的事情。那么如何减少和减少界面变化带来的前端变化呢?答案很简单,增加防腐层。Anti-corruptionlayerAnti-CorruptionLayer是领域驱动设计中的一个概念,用来隔离两个系统,允许两个系统在不知道对方领域知识的情况下进行集成。主要是在两个系统之间进行模型(model)或协议(protocol)的转换,最终目的是为了方便系统使用者而不是方便系统提供者。进一步的解释是将系统提供者的模型转换为系统消费者的模型。这个概念在前端的代码中实现起来很简单,可能只是一个关系映射函数。functiondataMap(rawData){//...logicreturnformatData;}现在,按照我们上面的理论搭建的系统,一共有三层,从下到上分别是防腐层,模型层,UI层,这样如图所示:这样搭建的系统,无论接口返回数据如何,数据格式是什么,都不会直接破坏我们的model层代码,更不会破坏这种破坏性的渗透到UI层的代码。当然,如果整个业务流程发生变化,这种颠覆会影响到各个层面,这是不可避免的。总结前端数据建模是开发大中型项目和产品的实用方法论。通过设计一个模型来帮助我们降低系统的复杂度,看起来非常有吸引力。但我们不能否认,前后端分离架构在业界流行已经有六七年了(2016年计算),前端数据建模从来没有统一过,也没有被视为一种的开发模式被广泛使用。那么我们不禁会想,前端数据建模是不是应该做的事情?根据我的经验,有以下几个原因:宏格式:前端程序员频繁跳槽。根据个人招聘经验和国内几家大型招聘平台的数据,前端程序员的平均跳槽频率不到一年。既然大家都是短期工作者,为什么还要考虑这种长期的事情呢?代码都变成“狗屎山”了,干脆不干了,我何必去死呢?不是我找不到工作。大多数公司不太重视前端质量。因为不管是大公司还是小公司,无论是传统行业还是互联网行业,都会更加重视数据的重要性。因为网站只是一种展示和操作数据的手段。数据决定流程和金钱。甚至很多传统行业的公司连UI都没有。只有中大型互联网公司才会有用户体验部门。既然公司不怎么重视,为什么要做呢?微商业态:从业人员层次偏低。前端门槛比较低,很多人还在摸不着头脑去实现一定的UI效果。他们怎么能把精力放在生意上呢?流程不行?找到后台哇。连问题都没有意识到的人怎么能解决呢?大多数大师不屑于接触业务。编译构建、框架、组件化、数据可视化、WebGL、CI/CD、LowCode/NoCode、工具链……前端可以深挖的方向太多了,但说到技术谁擅长,基本上都是以上这些,很少有人会说某人的业务代码写的好,技术牛逼。因为商业在大多数人眼里只是一个基本的操作。另外前面我也说过,前端的未来应该是交互和体验,而不是业务。但不管是什么原因,都不能否认前端数据建模对业务的意义和价值。永远记住,我们想成为工程师,而不是程序员。