I am not debating that immutable objects makes concurrent programming
easier - it is just that immutable objects do not model real world
(domain) objects very well.
If I have an instance of the car, and I paint it RED, I don't get a
new instance of the Car,
so
Car newCar = car.paint(RED)
is not good.
I want
car.paint(RED)
car.getColor() == RED
If I have two users that each want to paint the car a different
color, you have a conflict and some sort of synchronization and
ordering is required.
so it would be
sync(car) {
if(car.getColor()==BLACK)
car.paint(RED);
else
error you can't paint a non-black car
}
Immutable objects only seem to work well for objects with very few
properties.
A lot of concurrent programming deals with complex domain objects,
and thus external synchronization is required (in most cases).
On Oct 16, 2007, at 4:32 PM, Charles Miller wrote:
1) As a general design rule, objects that represent values should
be immutable.
There are a lot of practical advantages to having immutable value
objects: you can use them safely in sets and as keys in maps, you
can pool and flyweight them, and yes, they're much safer in a multi-
threaded environment. But these are side-effects of the fact that
making something immutable makes it an order of magnitude simpler,
conceptually.
The number 6 should always be the number 6. The string "blah"
should always be the string "blah". It doesn't make sense to
redefine the number 6 to have a value of 7. Values are concrete,
and that concreteness gives you the confidence that 6 + 7 will
_always_ give you the same result, whenever you happen to calculate
it.
(A friend of mine once told me of a project, I can't remember in
which language, where somebody accidentally redefined the empty
string. Hilarity ensued.)
2) Immutable objects are _safer_ than "thread-safe" objects
When an object says it is thread safe (StringBuffer, for example,
or the pre-1.2 collection classes), all it means is that the
_internal state of the object will remain consistent_ if the object
is used across multiple threads. It doesn't mean that the object
itself can be used across threads safely. For example, the
following (admittedly artificial) code:
public static BigInteger triple(BigInteger int)
{
return int.add(int).add(int);
}
This method is only reliable because BigInteger is immutable. Even
if you were to synchronize every single method on your mutable
BigInteger class, you would not be protecting it from having its
value changed halfway through the operation, leaving you with a
value that isn't three times anything, let alone the number you
passed in.
The safety that is generally promised by "thread safe" objects is
such a weak kind of safety that it is largely being abandoned as a
feature of the Java standard libraries. For the very rare case
where internal consistency across threads may be all that is
required, wrappers like Collections.synchronizedFoo() are provided.
It's really no accident that functional languages like Erlang,
where everything is an immutable value, are being touted as the
safe solution to multi-threaded programming. Safe multi-threaded
programming is HARD, and the more code you write that is provably
safe, the fewer times you're going to be up at 3am cursing at your
debugger.
There are a lot of really interesting papers out there about how
mechanisms like Java synchronization are simply the wrong way to
deal with the inherently non-deterministic nature of concurrent
applications, and inevitably lead to disaster, ruination and death.
3) Immutable objects are less efficient than mutable ones... but
most of the time you don't care.
Object allocation in Java is distressingly cheap. Garbage-
collection of young generation objects is reasonably inexpensive.
The Java language is _designed_ with the creation and destruction
of lots of little objects in mind, and it does it very well. As
such, it makes sense to err on the side of creating too many objects.
There are, of course, exceptions. That's why we profile code. For
the most common case where immutability can be a problem --
building strings -- Java offers a mutable StringBuilder. This is a
pretty common pattern: offer a builder class to construct objects
piecemeal, then have the immutable value pop out of the other end.
You've found a case where the immutable bignum classes in Java
aren't efficient enough for you, and the only alternative you have
is to abandon them and mess with arrays. The problem here isn't
that BigInteger and BigDecimal are immutable, having them be
immutable is the Right Thing To Do. The real problem is that
providing a high-performance library for arbitrary precision
arithmetic would _also_ be the Right Thing To Do, but Java doesn't.
I'm sure some exist, though. Have you tried Googling?
C
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Java-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden