摘要:结论三对于某些具体的模块,单向数据流不是万灵药,整体架构单向数据驱动,具体模块可以根据场景选择最合适的总结个人感觉数据驱动对于开发人员的要求其实有一些增加,开发是需要更多的全局观,对于业务需要更加的了解。
年前一篇文章《前端数据驱动的价值》聊了一下数据驱动的一些看法。
其中数据驱动的核心在于整个系统中对于数据的架构,设计,维护。对于数据的处理直接决定了系统的稳定性,可维护性,可扩展性。但是这里的数据维护也是相当复杂和难搞的一块。
精选评论引用nightire在segmentfault对于《前端数据驱动的价值》的评论:
我觉得非常好所以完整复制过来
数据驱动的陷阱数据驱动肯定不是从 flux/redux + react 才开始的
上者特别强调单向数据流,所以才给人造成“由它开始”的错觉单向数据流有一个前置依赖,那就是 Single Data Source,也就是你的“提线木偶”所描述的那样
然而在你的文章里却把它写成了 Data Driven 的前置依赖
问题来了:只有单向数据流才算数据驱动吗?
肯定不是的,其实老牌的 Angular/Ember/……等等都是一样的,无非就是对待 Data 的方式各有不同罢了;刨除这些细微差别,它们都是从 “DOM 驱动” 转向 “数据驱动” 的代表作品
只是它们并没有把这个的概念提炼的深入人心,如此说来,React 一家是功不可没的,不可变数据 + 单向数据流让数据驱动真正成为了“理念”,而不只是“概念”
然而,单向数据流也不是十全十美的,对于 UI 编程来说,有些地方的确是双向绑定来得更“漂亮”一些,比如:表单
所以 React 也适时的加入了双向绑定;不过这并不妨碍数据驱动这一理念得以贯彻
Single Data Source 也不是万能灵药,如果 A B C 三个模块都是各自独立开发的,之后因为需求而要合并在一起,怎么办?在它们之上再来一个 SDS?那这样还算不算是 SDS 呢?(或者反过来,不是 SDS 的话难道就不行吗?)
这个问题其实也还在发展中,这会儿我也给不出答案,只是客观描述一番罢了。
对于一个真正完美的数据驱动,就如同《前端数据驱动的价值》中的例子,所有业务全部由一个store驱动,维护好store就是维护好了整个系统。
但是对于这个一笔带过的维护store其实技术含量非常高。
下面分业务场景和情况描述
新项目这种情况是比较幸运的,开始的模型中设计好业务数据结构,设计好未来可扩展点。
当然,即使是新产品,也会遇到麻烦点,因为每一个参与开发的人,必须要全局的理解整个数据结构。
看看数据难搞的地方,举个例子:
模式A:
var store = { userInfo: { name: "test", age: "20" }, planNum: 2, plans: { "plan1": { name: "plan1", price: 2.00, unitNum: 1, unit: { "unit1": { name: "unit1", price: 1.22, keywordNum: 2, keyword: { "keyword1": { name: "word1", price: 22.00 }, "keyword2": { name: "word2", price: 21.00 } } } } }, "plan2": { name: "plan2", price: 3.00, unitNum: 0, unit: {} } } }
上面是一种最简单的数据结构,清晰的展现了plan、unit、keyword直接的关系,简单直白。
但是如果当层级关系越来越深,这个里面增删改查信息就是一个麻烦点,可以说上面结构的可扩展性不强。
那么换下面一种结构是否更加合适:
模式B:
var store = { userInfo: { name: "test", age: "20" }, planNum: 2, plans: { "plan1": { name: "plan1", price: 2.00, unitNum: 1, unit: [unit1] }, "plan2": { name: "plan2", price: 3.00, unitNum: 0, unit: [] } }, units: { "unit1": { plan: "plan1", name: "unit1", price: 1.22, keywordNum: 2, keyword: [keyword1] } }, keywords: { "keyword1": { plan: "plan1", unit: "unit1", name: "word1", price: 22.00 }, "keyword1": { plan: "plan1", unit: "unit1", name: "word2", price: 21.00 }, } }
个人感觉这种模式更加适合,便于查找和更新,那么问题来了,先抛开哪种数据结构更合适问题,假如开发初期模式A是ok的,随着业务的复杂,发现模式A越来越难维护,经过重新设计,发现转换到模式B更加合适,能明显提高开发和维护效率,那么怎么办?
个人还没有实践过,但是经验上看感觉是会导致大面积重构。即使重构完成,假如后期发现更好的数据模式呢?
所以可以看出初期的数据结构决定了未来架构,看上去像不像后端开发,数据库的设计很重要。
既然越来越像后端设计模式,那么是否会模仿当时的前后端分离策略,底层数据结构和业务展现通过api实现呢?个人感觉这样有点问题过于复杂化。那么是否可以加一个中间数据转换层去处理数据呢?这样在底层数据结构变换时,也能避免直接影响业务模块,中间层做一个适当的解耦,展示内容和数据结构没有什么关联,关联的仅仅是数据信息。
结论一:初期的数据结构设计会是未来的不定时炸弹,迟早会面对,需要有相应策略
模块合并再来考虑评论中的一个问题:
Single Data Source 也不是万能灵药,如果 A B C 三个模块都是各自独立开发的,之后因为需求而要合并在一起,怎么办?在它们之上再来一个 SDS?那这样还算不算是 SDS 呢?(或者反过来,不是 SDS 的话难道就不行吗?)
复杂的系统中确实会遇到这种问题,直接举例:
模块C,主要负责修改level:
var store = { moduleA: { "plan1": { name: "plan1", price: 22.00 }, level: 2 } }
模块D,主要负责修改auth:
var store = { moduleB: { "plan1": { name: "plan1", price: 22.00 }, auth: 0 } }
现在的逻辑是假如两个独立开发好的模块需要合并到一起,他们都有各自模块的内部数据结构,假如模块C除了修改level,还修改了plan1的name会怎么样?为了保证数据统一,需要去找到模块D中的plan1信息,并且修改。假如他们都合并到上面一个例子模块A中怎么办,是否还需要继续同步修改。如果漏掉一个同步,展示上,以及后面的处理都会引发各种bug。
当然,如果不用数据驱动,可能这种模块合并也是需要从展示层级各处同步修改信息的,也会特别麻烦。只是相比较而言,数据驱动的这种合并同步并没有给我们带来很清晰简单的处理方式。
结论二:数据驱动下,数据的重复和同步是一个坑,要尽量避免
不适合的场景然而,单向数据流也不是十全十美的,对于 UI 编程来说,有些地方的确是双向绑定来得更“漂亮”一些,比如:表单
评论里面提到的这部分应该是单向数据流的一个痛点,如果模块里面严格执行单向数据流,对于这种表单验证来说,是非常痛苦的。
例如:
var form = { value: 2.00 }
对应一个输入框,输入框只能限制输入1-100的2位小数。整个验证过程单向数据驱动就会特别麻烦。
一个简单的例子,在使用react实现表单验证就比较麻烦。
结论三:对于某些具体的模块,单向数据流不是万灵药,整体架构单向数据驱动,具体模块可以根据场景选择最合适的
总结个人感觉数据驱动对于开发人员的要求其实有一些增加,开发是需要更多的全局观,对于业务需要更加的了解。这个其实算是缺点,因为从工程化的角度,这种模式提高了开发成本,提高了开发人员的学习成本。
那么优点呢,应该是系统的稳定性,可维护性,健壮性会更好。
总之没有银弹,每种模式都有适合的场景。以上就是对于数据驱动的一点点看法。仅供参考。
微信公众号 个人博客http://tangguangyao.github.io/
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/78681.html
摘要:之前谈到过很多次数据驱动的理解,这次通过实际项目检验了一下自己的想法。对于数据驱动这种模式,至少从数据层,可以规避,做一层数据变化的效验这个和写服务端单侧差不多。数据驱动和有点类似,只是借用在单页面上实现了。 之前谈到过很多次数据驱动的理解,这次通过实际项目检验了一下自己的想法。 相关文件 《前端数据驱动的价值》 《前端数据驱动的陷阱》 项目详设 详设的重要性 对于复杂一点的项目,...
摘要:面试如何防骗一份优秀的前端开发工程师简历是怎么样的作为,有哪些一般人我都告诉他,但是他都不听的忠告如何面试前端工程师 更多资源请Star:https://github.com/maidishike... 文章转自:https://github.com/jsfront/mo... 3月份前端资源分享 1. Javascript 使用judge.js做信息判断 javascript...
摘要:对于大多数典型的企业应用而言,其性能表现几乎完全依赖于持久层的性能。速成法使用批处理对于批处理程序,驱动程序提供了旨在减少网络来回传输的优化方法。速成法检查错误的提交间隔如果你使用批处理程序,提交间隔会对性能造成十倍甚至百倍的影响。 对于大多数典型的 Spring/Hibernate 企业应用而言,其性能表现几乎完全依赖于持久层的性能。此篇文章中将介绍如何确认应用是否受数据库约束,同时...
摘要:使用闭包遇到的陷阱一陷阱在类的原型对象中添加特权方法首先定义一个类,该类中有一个私有变量定义个特权方法来访问修改私有变量然后我们对类进行测试到目前为止,类正常工作。 使用JavaScript闭包遇到的陷阱(一) 陷阱:在类的原型对象中添加特权方法 首先定义一个Page类,该类中有一个私有变量dom: function Page(){ var dom; } 定义2个特权方法来访问...
摘要:随着标准的普及,已经拥有许多新的语法糖,这让我们编写可读的,高质量的代码变得更加方便,但即使这样仍然会遇到一些潜在的陷阱。例如集合的最终长度是,由于两次添加的数组不是同一个。最终会得到大小为的集合,因为字符串是不可变。 showImg(https://segmentfault.com/img/remote/1460000019006033); 随着ES6标准的普及,JavaScript...
阅读 2521·2023-04-26 02:57
阅读 1403·2023-04-25 21:40
阅读 2155·2021-11-24 09:39
阅读 3557·2021-08-30 09:49
阅读 760·2019-08-30 15:54
阅读 1166·2019-08-30 15:52
阅读 2068·2019-08-30 15:44
阅读 1274·2019-08-28 18:27