Questions tagged «immutability»

23
如果不可变的对象很好,那么人们为什么继续创建可变的对象?[关闭]
如果不变的对象¹很好,简单并且可以在并发编程中受益,那么为什么程序员会继续创建可变的对象²? 我有4年的Java编程经验,正如我所看到的,创建类之后,人们要做的第一件事就是在IDE中生成getter和setter(因此使其可变)。是否缺乏意识,或者在大多数情况下我们能否摆脱使用可变对象的困扰? ¹ 不可变对象是创建后状态无法修改的对象。 ² 可变对象是创建后可以修改的对象。

6
Java 8为什么不包含不可变的集合?
Java团队做了很多出色的工作,消除了Java 8中函数编程的障碍。特别是,对java.util集合的更改在将转换链接到非常快速的流式操作方面做得很好。考虑到他们在集合上添加一流的函数和函数方法做得多么出色,为什么他们完全无法提供不可变的集合甚至不可变的集合接口呢? 在不更改任何现有代码的情况下,Java团队可以随时添加与可变接口相同的不可变接口,减去“ set”方法并使现有接口从其扩展,如下所示: ImmutableIterable ____________/ | / | Iterable ImmutableCollection | _______/ / \ \___________ | / / \ \ Collection ImmutableList ImmutableSet ImmutableMap ... \ \ \_________|______________|__________ | \ \___________|____________ | \ | \___________ | \ | \ | List Set Map ... 当然,诸如List.add()和Map.put()之类的操作当前会返回给定键的布尔值或先前值,以指示该操作是成功还是失败。不可变集合必须将此类方法视为工厂,并返回包含添加元素的新集合-该集合与当前签名不兼容。但这可以通过使用其他方法名称(例如ImmutableList.append()或.addAt()和ImmutableMap.putEntry())来解决。由此产生的冗长性将远远超过使用不可变集合的好处所抵消,并且类型系统将防止调用错误方法的错误。随着时间的流逝,旧的方法可能会被弃用。 永恒收藏的胜利: 简单性-当基础数据不变时,关于代码的推理就更简单了。 文档-如果某个方法采用不可变的集合接口,则您将知道它不会修改该集合。如果某个方法返回一个不可变的集合,则说明您无法对其进行修改。 并发-不可变集合可以在线程之间安全地共享。 …

6
不变性是否会损害JavaScript的性能?
JavaScript中似乎有一种趋向于将数据结构视为不变的趋势。例如,如果您需要更改一个对象的单个属性,则最好使用新属性创建一个全新的对象,然后从旧对象复制所有其他属性,然后对旧对象进行垃圾回收。(那是我的理解。) 我最初的反应是,这听起来会降低性能。 但是后来,像Immutable.js和Redux.js这样的库是由比我更聪明的人编写的,并且似乎对性能有很强的关注,因此使我怀疑我对垃圾的理解(及其对性能的影响)是否错误。 我所缺少的不变性是否具有性能优势,它们是否超过了创建大量垃圾的弊端?


4
为什么在接口中使用“可选方法”实现Java集合?
在扩展Java集合框架的第一个实现过程中,我很惊讶地看到集合接口包含声明为可选方法的方法。如果不支持,则期望实现者抛出UnsupportedOperationExceptions。这立即让我感到震惊,因为它是糟糕的API设计选择。 在阅读了约书亚·布洛赫(Joshua Bloch)出色的“有效Java”(Effective Java)书之后,后来得知他可能对这些决定负有责任,但似乎并没有遵循书中所遵循的原则。我想声明两个接口:Collection和MutableCollection,它通过“可选”方法扩展Collection,将导致可维护性更高的客户端代码。 还有的问题一个很好的总结在这里。 是否有充分的理由为什么选择了可选方法而不是两个接口实现?

5
什么时候在akka / erlang中使用actor不好?
我每天与akka合作7-8个月。当我开始时,我将在应用程序上工作,并注意到actor基本上会在actor系统内部的任何地方用于大多数对象之间的通信。所以我也做同样的事情-为x / y / z旋转另一个演员。 在我看来,这可能太过随意了,在不需要的地方增加了复杂性-但是我找不到关于应该使用参与者与普通同步甚至是期货的异步逻辑的讨论。我的同事提到类似的内容后,我开始思考自己的立场。我最近才意识到有几种情况,我在考虑一个任务,然后避免创建另一个参与者,因为我可以在不可变的实现中安全地实现相同的结果-例如,从数据库或文件中获取配置值的地方,而这些地方很少访问并且会等待结果是实际用例。 尤其是在我看来,在任何情况下,如果您正在使用不可变状态,参与者都会造成复杂性并限制吞吐量-例如,对象中的纯函数可以在没有任何并行级别的情况下并发调用,但是演员一次只能处理一条消息。另一个考虑因素是,如果您需要等待结果,除非您开始使用期货,否则就将线程停放,但是在不需要担心异步消息传递或扩展的情况下,聘请演员似乎过大。 所以我的问题是-使用演员的时间不好吗?我很好奇erlang看起来如何并且真的希望别人的见识。或者,如果有一些有关演员使用的原则。

9
没有并发性时,不变性是否值得?
似乎总是/经常提到线程安全是使用不可变类型(尤其是集合)的主要好处。 我有一种情况,我想确保方法不会修改字符串字典(在C#中是不可变的)。我想尽可能地约束事物。 但是,我不确定将依赖项添加到新程序包(Microsoft不可变集合)是否值得。性能也不是大问题。 因此,我想我的问题是,在没有硬性能要求且没有线程安全问题的情况下,是否强烈建议使用不可变集合?考虑一下值语义(在我的示例中)可能是也可能不是要求。

2
艾伦·凯(Alan Kay)在“ Smalltalk的早期历史”中的“分配”是什么意思?
我一直在阅读《 Smalltalk的早期历史》,并且提到了“分配”,这使我质疑其含义: 尽管OOP来自许多动机,但其中两个是核心。大型方案是为包含细节隐藏的复杂系统找到一种更好的模块方案,而小型方案是找到一种更灵活的分配方案,然后尝试将其彻底消除。 (从1960-66年开始-早期的OOP和六十年代的其他形成性思想,第一部分) 我从Simula得到的是,您现在可以用目标替换绑定和分配。您希望任何程序员做的最后一件事就是内部状态混乱,即使以图形方式呈现也是如此。相反,应该将对象呈现为更适合用作动态组件的更高级别行为的站点。(...)不幸的是,当今所谓的“面向对象程序设计”中的大部分只是带有奇特构造的旧式程序设计。许多程序现在都通过“昂贵的附加程序”来完成“分配样式”操作。 (摘自“面向对象”样式,第IV节) 我将目的解释为对象是外观,而目的是在对象上设置实例变量(即“赋值”)的任何方法(或“消息”)都违反了目的,我是否正确?第四节中的以下两个陈述似乎支持了这种解释: 一起使用的四种技术-持久状态,多态性,实例化和作为目标的方法-占据了很大的力量。这些都不要求使用“面向对象的语言”-ALGOL 68几乎可以转变为这种样式-OOPL只是将设计师的思想集中在一个特定的富有成果的方向上。但是,正确执行封装不仅是对状态抽象的承诺,而且是从编程中消除面向状态的隐喻的承诺。 ...和: 分配语句(甚至是抽象的语句)表达了非常低级的目标,需要更多的目标才能完成任务。通常,我们不希望程序员弄乱状态,无论是否模拟。 可以这样说,鼓励不透明,不可变的实例吗?还是不鼓励直接改变状态?举例来说,如果我有一个BankAccount类,它的确定有GetBalance,Deposit和Withdraw实例方法/消息; 只需确保没有SetBalance实例方法/消息?

7
完整的不变性和面向对象的编程
在大多数OOP语言中,对象通常是可变的,只有少数例外(例如,python中的元组和字符串)。在大多数功能语言中,数据是不可变的。 可变对象和不可变对象都带来了它们自己的优点和缺点的完整列表。 有一些语言试图将两个概念结合起来,例如scala,其中您拥有(明确声明的)可变和不可变的数据(如果我错了,请更正我,我对scala的了解远远超过了限制)。 我的问题是:在OOP上下文中,完全(原文如此)不变性(即对象一旦创建就不能变异)是否有意义? 是否有这种模型的设计或实现? 基本上,(完整的)不变性和OOP是对立的还是正交的? 动机:在OOP中,您通常对数据进行操作,更改(变异)基础信息,并在这些对象之间保留引用。例如,类的对象Person具有father引用另一个Person对象的成员。如果更改父亲的名字,则该子对象立即可见,无需更新。由于不可变,您将需要为父亲和孩子构造新的对象。但是与共享对象,多线程,GIL等相比,您将减少很多麻烦。

5
不变性是否完全消除了多处理器编程中对锁的需求?
第1部分 显然,不变性可以最大程度地减少多处理器编程中对锁的需求,但是它消除了这种需求吗?还是存在仅不变性还不够的情况?在我看来,您只能推迟处理和封装状态,直到大多数程序必须实际执行某些操作(更新数据存储,生成报告,引发异常等)之前。这样的动作能否始终不加锁地进行?扔掉每个对象并创建一个新对象而不是更改原始对象(对不变性的粗略看法)的纯粹行动是否提供了对进程间争用的绝对保护,还是有些仍然需要锁定的情况? 我知道很多函数式程序员和数学家都喜欢谈论“无副作用”,但是在“现实世界”中,所有事情都有副作用,即使这是执行机器指令所需的时间。我对理论/学术答案和实际/现实答案都感兴趣。 如果不变性是安全的,那么在给定某些界限或假设的情况下,我想知道“安全区”的边界到底是什么。可能的边界的一些示例: 输入输出 异常/错误 与其他语言编写的程序的交互 与其他机器(物理,虚拟或理论上的机器)的交互 特别感谢@JimmaHoffa 的评论,这开始了这个问题! 第2部分 多处理器编程通常用作优化技术-使某些代码运行更快。什么时候使用锁和不可变对象更快? 考虑到阿姆达尔定律所规定的限制,与可变对象锁定相比,什么时候可以实现更好的整体性能(考虑或不考虑垃圾收集器)? 摘要 我将这两个问题合并为一个,以尝试了解边界不变性在哪里作为线程问题的解决方案。

7
不可变与const之间的区别
我经常看到这些术语,immutable并且const可以互换使用。但是,从我的(很少)经验来看,两者在代码中的“合同”上有很大不同: 不可变,使合同,这个对象就不会改变,任何(如Python的元组,Java字符串)。 Const使合约在此变量的范围内不被修改(不保证在此期间,其他线程可能会对指向的对象执行任何操作,例如C / C ++关键字)。 显然,除非语言是单线程(PHP)或具有线性或唯一性键入系统(Clean,Mercury,ATS),否则两者并不等效。 首先,我对这两个概念的理解正确吗? 第二,如果有区别,为什么它们几乎只能互换使用?

5
不要为不可变对象声明接口
不要为不可变对象声明接口 [编辑]所涉及的对象代表数据传输对象(DTO)或纯旧数据(POD) 这是一个合理的指导方针吗? 到目前为止,我经常为不可变(无法更改数据)的密封类创建接口。我一直在小心谨慎,不要在我关心不变性的任何地方使用该接口。 不幸的是,界面开始渗透代码(这不仅仅是我担心的代码)。您最终要通过一个接口,然后又想将其传递给某些代码,而这些代码确实想假设要传递给它的东西是不可变的。 由于这个问题,我正在考虑永远不要为不可变对象声明接口。 这可能会对单元测试产生影响,但是除此之外,这似乎是一个合理的指南吗? 还是我应该使用另一种模式来避免出现“扩展接口”问题? (我之所以使用这些不可变的对象,有几个原因:主要是出于线程安全,因为我编写了许多多线程代码;还因为这意味着我可以避免将防御性的对象副本传递给方法。代码变得更加简单在很多情况下,当您知道某事物是不可变的时,如果您已经获得了接口,那么您就不会知道这一点。事实上,如果您不提供通过接口引用的对象的防御性副本,通常情况下您甚至无法克隆操作或序列化的任何方式...) [编辑] 由于我想使对象不可变的原因,为了提供更多上下文,请参阅Eric Lippert的这篇博客文章: http://blogs.msdn.com/b/ericlippert/archive/tags/immutability/ 我还应该指出,我在这里使用一些较低级别的概念,例如在多线程作业队列中正在操纵/传递的项目。这些本质上是DTO。 约书亚·布洛赫(Joshua Bloch)也在他的《有效的Java》一书中建议使用不可变对象。 跟进 谢谢您的反馈。我已经决定继续使用该指导原则,以适用于DTO及其同类。到目前为止,它运行良好,但是只有一个星期了……看起来还不错。 我还想问一些与此有关的其他问题;尤其是我所说的“深层或浅层不变性”(我从深层和浅层克隆中窃取的术语)-但这是另一个问题。
27 c#  immutability 

7
有什么实际的方法可以使链接的节点结构不可变?
我决定编写一个单链接列表,并制定了使内部链接节点结构不可变的计划。 不过我遇到了障碍。说我有以下链接的节点(来自先前的add操作): 1 -> 2 -> 3 -> 4 并说我想附加一个5。 为此,由于node 4是不可变的,因此我需要创建的新副本4,但将其next字段替换为包含的新节点5。现在的问题是3参考旧的4;没有附加的5。现在,我需要复制3,并替换其next字段以引用4副本,但是现在2引用的是旧版本3... 换句话说,要执行追加操作,似乎需要复制整个列表。 我的问题: 我的想法正确吗?有什么办法可以执行追加操作而不复制整个结构? 显然,“有效Java”包含以下建议: 类应该是不可变的,除非有充分的理由使它们可变。 这是变异性的好例子吗? 我认为这不是建议答案的重复,因为我不是在谈论清单本身。显然,它必须是可变的才能符合该接口(无需执行诸如在内部保留新列表并通过getter检索它的操作。不过,经过深思熟虑,即使这样也需要进行一些修改;将其保持在最低限度)。我说的是列表的内部是否必须不可变。

8
数据库设计中的不变性
约书亚·布洛赫(Joshua Bloch)的《有效的Java》中的一项内容是,类应允许实例的变异尽可能少,最好根本不允许变异。 通常,对象的数据会保存到某种形式的数据库中。这使我开始思考数据库中的不变性,特别是对于那些代表较大系统中单个实体的表而言。 我最近一直在尝试的一种想法是尝试最小化我对代表这些对象的表行的更新,并尝试尽可能多地执行插入。 我最近正在尝试的一个具体示例。如果我知道以后可以在记录中附加其他数据,我将创建另一个表来表示该表,类似于以下两个表定义: create table myObj (id integer, ...other_data... not null); create table myObjSuppliment (id integer, myObjId integer, ...more_data... not null); 希望这些名字不是一字不漏的,只是为了说明这个想法。 这是数据持久性建模的合理方法吗?是否值得尝试限制在表上执行的更新,尤其是对于最初创建记录时可能不存在的数据填充空值?有时候这样的方法以后可能会引起严重的疼痛吗?

4
如何处理不可变字段上的setter?
我有一堂课有两个readonly int领域。它们作为属性公开: public class Thing { private readonly int _foo, _bar; /// <summary> I AM IMMUTABLE. </summary> public Thing(int foo, int bar) { _foo = foo; _bar = bar; } public int Foo { get { return _foo; } set { } } public int Bar { get { return …

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.