不变性的逆向观点
TL/DR:在 JavaScript 中,不可变性更像是一种时尚趋势,而不是必需品。如果你正在使用 React,它确实为状态管理中一些令人困惑的设计选择提供了一个简洁的解决方法。然而,在大多数其他情况下,它不会增加足够的价值,因为它引入了复杂性,更多的是填充简历而不是满足实际的客户需求。
长答案:请阅读以下内容。
为什么不可变性在javascript中如此重要(或需要)?
好吧,我很高兴你问!
不久前,一位名叫Dan Abramov的非常有才华的人写了一个名为Redux的javascript状态管理库,它使用纯函数和不变性。他还制作了一些非常酷的视频,使这个想法非常容易理解(和销售)。
时机很完美。Angular的新颖性正在消退,JavaScript世界已经准备好专注于具有适当程度的冷却度的最新事物,这个库不仅具有创新性,而且与另一个硅谷巨头兜售的React完美契合。
尽管可能很可悲,但时尚在JavaScript世界中占主导地位。现在,阿布拉莫夫被誉为半神,我们所有凡人都必须让自己屈服于不变性的道......无论它是否有意义。
变异对象有什么问题?
无!
事实上,程序员一直在为er...只要有对象变异。换句话说,50多年的应用程序开发经验。
为什么要使事情复杂化?当你有对象并且它死了,你真的需要一秒钟来跟踪变化吗?大多数人只会说完并完成它。cat
cat
cat.isDead = true
(变异对象)不是让事情变得简单吗?
是的!。。当然可以!
特别是在JavaScript中,它在实践中最有用,用于呈现在其他地方(如数据库中)维护的某个状态的视图。
如果我有一个必须更新的新新闻对象,该怎么办?...在这种情况下,我如何实现?删除商店并重新创建它?将对象添加到数组中不是一种成本较低的操作吗?
好吧,您可以采用传统方法并更新对象,以便该对象的内存中表示形式会发生变化(以及向用户显示的视图,或者人们希望如此)...News
或者...
您可以尝试性感的FP / Immutability方法,并将对对象的更改添加到跟踪每个历史更改的数组中,以便您可以循环访问数组并找出正确的状态表示形式(哎呀!News
我试图了解这里有什么。请启发我:)
时尚来来去去的伙伴。有很多方法可以剥猫皮。
很抱歉,您必须忍受一组不断变化的编程范式的混乱。但是,嘿,欢迎来到俱乐部!
现在,关于不变性,有几个要点要记住,你会得到这些以只有天真才能聚集的狂热强度抛给你。
1)不变性对于避免多线程环境中的竞争条件非常棒。
多线程环境(如C++、Java 和 C#)在多个线程想要更改对象时会锁定对象。这对性能不利,但比数据损坏的替代方案更好。然而,这还不如让一切变得一成不变(主赞美哈斯克尔!)。
但是,唉!在JavaScript中,你总是在单个线程上运行。甚至是Web工作者(每个工作线程都在单独的上下文中运行)。因此,由于您不能在执行上下文中具有与线程相关的争用条件(所有这些可爱的全局变量和闭包),因此支持不可变性的主要观点就消失了。
(话虽如此,在Web worker中使用纯函数有一个优点,那就是你对在主线程上摆弄对象没有任何期望。
2) 不可变性可以(以某种方式)避免应用状态中的争用条件。
这是问题的真正症结所在,大多数(React)开发人员会告诉你,不可变性和FP可以以某种方式发挥这种魔力,使应用程序的状态变得可预测。
当然,这并不意味着你可以避免数据库中的竞争条件,要做到这一点,你必须协调所有浏览器中的所有用户,为此,你需要一个后端推送技术,如WebSockets(下面有更多内容),它将向运行该应用程序的每个人广播更改。
这并不意味着JavaScript中存在一些固有的问题,你的应用程序状态需要不可变性才能变得可预测,任何在 React 之前一直在编写前端应用程序的开发人员都会告诉你这一点。
这个相当令人困惑的声明仅仅意味着,如果你使用React,你的应用程序很容易出现竞争条件,但这种不可变性可以让你消除这种痛苦。为什么?因为 React 很特别。它首先被设计为一个高度优化的渲染库,状态管理被颠覆到这个目标,因此组件状态通过一个异步事件链(又名“单向数据绑定”)进行管理,这些事件可以优化渲染,但你无法控制并依赖于你记住不要直接改变状态......
鉴于这种情况,很容易看出对不可变性的需求与JavaScript几乎没有关系,而与React有很大关系:如果你的新应用程序中有一堆相互依赖的变化,并且没有简单的方法来弄清楚你目前的状态,你会感到困惑, 因此,使用不可变性来跟踪每个历史变化是完全有意义的。
3)竞争条件绝对不好。
好吧,如果你使用的是 React,它们可能是。但是,如果您选择不同的框架,则很少见。
此外,您通常有更大的问题需要处理...像依赖地狱这样的问题。就像一个臃肿的代码库。就像你的CSS没有被加载一样。就像一个缓慢的构建过程或被困在一个整体式后端,这使得迭代几乎是不可能的。就像没有经验的开发人员不了解发生了什么,把事情搞得一团糟。
你知道的。现实。但是,嘿,谁在乎呢?
4) 不可变性利用引用类型来减少跟踪每个状态更改对性能的影响。
因为说真的,如果你每次的状态发生变化时都要复制东西,你最好确保你是聪明的。
5)不变性允许您撤消内容。
因为呃..这是您的项目经理将要要求的头号功能,对吧?
6)不可变状态与WebSockets结合使用具有许多很酷的潜力
最后但并非最不重要的一点是,状态增量的累积与WebSockets结合使用是一个非常引人注目的案例,它允许将状态作为不可变事件的流轻松使用...
一旦这个概念落下了一分钱(状态是事件的流动 - 而不是代表最新观点的一组粗糙的记录),不可变的世界就变成了一个神奇的居住地。一个超越时间本身的事件来源的奇迹和可能性的土地。如果做得好,这绝对可以使实时应用程序更容易完成,你只需将事件流广播给每个感兴趣的人,这样他们就可以建立自己的当下表示,并将自己的更改写回公共流中。
但在某些时候,你醒来时会意识到,所有这些奇迹和魔法都不是免费的。与你热切的同事不同,你的利益相关者(是的,付钱给你的人)很少关心哲学或时尚,而是关心他们为制造可以销售的产品而支付的钱。最重要的是,更难为不可变性编写代码,并且更容易破坏它,而且如果你没有后端来支持它,那么拥有不可变的前端就没有多大意义。当你最终说服你的利益相关者你应该通过像WebSockets这样的推送技术来发布和使用事件时,你就会发现在生产中扩展是多么痛苦。
Now for some advice, should you choose to accept it.
A choice to write JavaScript using FP/Immutability is also a choice to make your application code-base larger, more complex and harder to manage. I would strongly argue for limiting this approach to your Redux reducers, unless you know what you are doing... And IF you are going to go ahead and use immutability regardless, then apply immutable state to your whole application stack, and not just the client-side, as you're missing the real value of it otherwise.
Now, if you are fortunate enough to be able to make choices in your work, then try and use your wisdom (or not) and do what's right by the person who is paying you. You can base this on your experience, on your gut, or whats going on around you (admittedly if everyone is using React/Redux then there a valid argument that it will be easier to find a resource to continue your work).. Alternatively, you can try either Resume Driven Development or Hype Driven Development approaches. They might be more your sort of thing.
In short, the thing to be said for immutability is that it will make you fashionable with your peers, at least until the next craze comes around, by which point you'll be glad to move on.
Now after this session of self-therapy I'd like to point out that I've added this as an article in my blog => Immutability in JavaScript: A Contrarian View. Feel free to reply in there if you have strong feelings you'd like to get off your chest too ;).