可变对象与不可变对象 [英] Mutable vs immutable objects

查看:291
本文介绍了可变对象与不可变对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图让我的头围绕可变对象和不可变对象。使用可变对象可能会遇到很多不便之处(例如从方法返回一串字符串),但是我无法理解这些负面影响。使用可变对象的最佳做法是什么?你应该尽可能避免他们吗?

解决方案

嗯,这有几个方面。第一,无参考身份的可变对象可能会在奇怪的时间引起错误。例如,考虑一个基于价值的等于方法的 Person bean:

 映射< Person,String> map = ... 
Person p = new Person();
map.put(p,嘿,那里!);

p.setName(丹尼尔);
map.get(p); // => null

个人实例获取丢失在地图中用作密钥,因为它是 hashCode ,并且基于可变值的相等性。这些值在地图之外变化,所有的哈希变得过时了。理论家们喜欢在这一点上竖琴,但实际上我没有发现太多的问题。



另一个方面是你的逻辑合理性码。这是一个难以定义的术语,涵盖从可读性到流程的一切。一般来说,您应该可以看一段代码,轻松了解它的作用。但更重要的是,您应该能够说服自己,它正确地执行正确。当对象可以通过不同的代码域独立变化时,有时变得难以跟踪什么是在哪里和为什么(远距离的幽灵行动)。这是一个比较困难的概念,但它是经常面临更大,更复杂的架构。



最后,可变对象是 killer 并发情况。每当您从单独的线程访问可变对象时,都必须处理锁定。这样可以降低吞吐量,并使您的代码更加难以维护。一个足够复杂的系统使这个问题远远超出了几乎不可能维持的几率(即使是并发专家)。



不可变对象(更特别是不可变的集合)避免所有这些问题。一旦你了解自己的工作原理,你的代码将会发展成一个更容易阅读,更易于维护,并且不太可能以奇怪和不可预测的方式失败的东西。不可变的对象更容易测试,这不仅是因为它们容易的可操作性,还包括他们倾向于执行的代码模式。简而言之,他们是周到的好习惯!



就此而言,我在这件事上几乎不是狂热者。当一切都不变时,一些问题就不会很好地模拟。但是我认为你应该尝试尽可能多地推送这个方向的代码,假设你使用的语言使得这是一个成功的观点(C / C ++使Java变得非常困难) 。简而言之:优势在某种程度上取决于你的问题,但我倾向于不偏不倚。


I'm trying to get my head around mutable vs immutable objects. Using mutable objects gets a lot of bad press (e.g. returning an array of strings from a method) but I'm having trouble understanding what the negative impacts are of this. What are the best practices around using mutable objects? Should you avoid them whenever possible?

解决方案

Well, there are a couple aspects to this. Number one, mutable objects without reference-identity can cause bugs at odd times. For example, consider a Person bean with an value-based equals method:

Map<Person, String> map = ...
Person p = new Person();
map.put(p, "Hey, there!");

p.setName("Daniel");
map.get(p);       // => null

The Person instance gets "lost" in the map when used as a key because it's hashCode and equality were based upon mutable values. Those values changed outside the map and all of the hashing became obsolete. Theorists like to harp on this point, but in practice I haven't found it to be too much of an issue.

Another aspect is the logical "reasonability" of your code. This is a hard term to define, encompassing everything from readability to flow. Generically, you should be able to look at a piece of code and easily understand what it does. But more important than that, you should be able to convince yourself that it does what it does correctly. When objects can change independently across different code "domains", it sometimes becomes difficult to keep track of what is where and why ("spooky action at a distance"). This is a more difficult concept to exemplify, but it's something that is often faced in larger, more complex architectures.

Finally, mutable objects are killer in concurrent situations. Whenever you access a mutable object from separate threads, you have to deal with locking. This reduces throughput and makes your code dramatically more difficult to maintain. A sufficiently complicated system blows this problem so far out of proportion that it becomes nearly impossible to maintain (even for concurrency experts).

Immutable objects (and more particularly, immutable collections) avoid all of these problems. Once you get your mind around how they work, your code will develop into something which is easier to read, easier to maintain and less likely to fail in odd and unpredictable ways. Immutable objects are even easier to test, due not only to their easy mockability, but also the code patterns they tend to enforce. In short, they're good practice all around!

With that said, I'm hardly a zealot in this matter. Some problems just don't model nicely when everything is immutable. But I do think that you should try to push as much of your code in that direction as possible, assuming of course that you're using a language which makes this a tenable opinion (C/C++ makes this very difficult, as does Java). In short: the advantages depend somewhat on your problem, but I would tend to prefer immutability.

这篇关于可变对象与不可变对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆