While reading akka docs right under messages and immutability section, It mentions about "explicitly exposing the state" inside case class. So my questions are;
What is meant by saying "explicitly exposing the state" for case class?
In order to achieve immutability, isn't it enough to write "case" for a class? Or I should be careful about its usage ?
The actor below represents its state with a mutable
Set[Int]
, which is initialized with the values1
,2
, and3
:When this actor receives a
GetState
message, it wraps its state in theState
case class and sends that to the sender. Even though theState
case class is immutable, its parameters
is a mutableSet
. Therefore, whenMyActor
creates aState
instance with its state and sends that as a message to the sender of theGetState
message,MyActor
's state becomes modifiable outside of the boundaries ofMyActor
itself. To make this concrete, let's sayAnotherActor
sends aGetState
message toMyActor
, at which pointMyActor
sends its state toAnotherActor
. Here is the latter actor:AnotherActor
modifiesMyActor
's state by removing2
from it, even though that state is delivered inside a case class.To mitigate this sort of leak, restrict mutability to the actor itself. In this example, instead of having a
val state = mutable.Set(1, 2, 3)
, define avar state = immutable.Set(1, 2, 3)
:Here,
MyActor
can safely send its state as a message because it's an immutableSet
(we could wrap theSet
inside a case class, but that's not essential in this case).No. When using a case class for actor messaging, ensure that all of the class's parameters are themselves immutable.
Yes.
I presume you're referring to this particular quote:
In their simplest form, a case class constructor's parameters will be mapped to 'val' fields and hence their reference will be immutable. However if the field itself is mutable (e.g. referencing a mutable collection or object) and you expose that (via an accessor method, say), then the class will become mutable (since you've exposed a mutable field). Not that you can still change the state internally, however, if you so wish.
I believe it refers to doing something like
Broken
is superficially immutable, because none of its fields can be directly set to anything, but it can still be altered by updatingm
, which will cause the behavior of the containingBroken
to change (hashCode
,equals
, etc.), thereby breaking anything that relies on those being consistent.m
corresponds toBroken
's internal (mutable) state, and exposing it allowsBroken
to be mutated, too.