5
1
I'm working (a bit) on a (turn-based strategy) game. There are two classes relevant for the question:
State: This is an immutable class, which exposes all its fields (either via getters or another way, as I felt appropriate). The state is a bit complicated, so I decomposed it into several classes in the package...stateCommand: This is an abstract immutable class with a couple of subclasses likeMoveCommand(Field from, Field to),PassCommand(),BidCommand(int amount), etc. in the package...command. All of fields have public getters.
I need one of the two methods
State Command.applyTo(State)orState State.apply(Command)
returning the new state (obtained by applying the command to the state).
Using the first method looks better at the first sight, since it dispatches to different implementations of applyTo in the subclasses of Command. Unfortunately, it forces me to fiddle with the many details of State in the class Command. In order to make it work, I need something like MutableState, or State.Builder, or a many-args constructor of State, or whatever.
Using the second method looks ugly, as it'd force me to use instanceof (or some other ugly way to simulate the virtual method dispatch). OTOH, it would concentrate the working with State in the class itself.
So I think the first method is the way to go. With Command and State each in its own package it means that MutableState (or whatever gets used for building the resulting State) need to be a public class since there are no friends in Java. No real problem, but not nice, is it?
So what is the proper design?
4Why is State immutable? That's almost contradictory. Immutable means stateless. Stateful means mutable. I don't get why you've created this problem for yourself. Can you explain further how state can be immutable? – S.Lott – 2011-09-12T21:57:12.283
@S.Lott: I don't claim it's a good idea. The
Statenever changes, it just gets replaced by another one (created from theMutableState). I'm considering dropping immutability but it wouldn't help much: The problem ofCommandfiddling with its data remains. – maaartinus – 2011-09-12T22:25:01.797"The problem of Command fiddling with its data remains"? The state has an API, does it not? The
Commanduses that API to make change to the state, correct? How is this a "problem"? Please be more specific. – S.Lott – 2011-09-12T22:41:50.3071I'm leaning towards S.lott's thinking here. To me, State should be mutable, although strictly bounded through an enum or similar tight design. YMMV of course – Martijn Verburg – 2011-09-12T23:10:00.017
If you made
Stateimmutable for threading reasons, consider whether copying it would be preferable (then mutating it). Alternatively, some immutable classes return copies of themself from setter methods - JodaTime returns a newDateTimeinstance every time theaddMinutes(1)method is called - this allows the methods to be chained as appropriate. – Clockwork-Muse – 2011-09-12T23:29:36.577@Martijn Verburg: "State should be mutable". To me they are synonyms. Stateful == Mutable. I don't understand how it can be otherwise, and I'm hoping for an explanation of a stateless state object. – S.Lott – 2011-09-12T23:41:03.033
@S. Lott, in Python and similar languages, integers are immutable but that doesn't prevent them from representing state. – Winston Ewert – 2011-09-13T00:07:16.080
@Winston Ewert: Um. That's not a very good example. You usually represent state with a mutable variable and assign an integer value to that variable. Representing state as "2" isn't sensible. Representing state as
count= 2is sensible. The value ofcountchanges. That's what state usually means. I'm hoping for an example of state that doesn't involve variables (or attributes of an object) that don't change. – S.Lott – 2011-09-13T00:42:01.7801@S. Lott, but that's exactly with the OP is doing. He's just got an object which is much more complex then a 2. He was a pointer to the current state. To change the state he replaces the object that pointer points to. Just like how you'd increment a count by replacing the integer object. – Winston Ewert – 2011-09-13T00:54:10.420
@Winston Ewert: If, indeed, the "state" is just a really complex object, then a few static copies would be sufficient. However, "forces me to fiddle with the many details of State in the class Command" says that it's not that simple. It says that there's some details to the state and an immutable object isn't appropriate somehow. Rather than conjecture, I'm looking for concrete details. – S.Lott – 2011-09-13T01:55:34.390
@S. Lott, I don't think the immutable object is appropriate. But I think he used one. – Winston Ewert – 2011-09-13T02:08:29.877
@Winston Ewert: You understood me correctly, and maybe immutability was indeed a bad idea here. Or maybe the only problem is that I've created an ugly API and it was just the ugliness which led to this question. – maaartinus – 2011-09-13T09:20:14.763
@maaartinus - Right, so I think the answer is to perhaps explore a mutable design. It may seem like you're throwing away some existing work, but that's not necessarily a bad thing - you've just basically done some exploratory programming :-). – Martijn Verburg – 2011-09-13T15:49:03.877