6

I am creating the model part of an MVC architecture. My one class will provide all the accesses to allow one to fetch system state. I want most of this state to be immutable as it shouldn't be changed and I don't want anyone accessing my model to be able to break the state by making a foolish change.

However, The objects representing the state have a bit of a tree structure. object A contains a set of B which contains a set of objects C which contain a set of Object D etc etc. Due to the nature of how I have to fetch the data I can't build the structure from the bottom up; the bottom most 'chid object' will be generated after all the others are completed. This is making it rather inconvenient to build the immutable objects in an intuitive manner, I want to add a set as my last phase of building but I can't if I already built immutable objects.

I know of three approaches, but not sure I like any. One is a builder patern, but keeping track of all the builders for a complicated structure until I'm done seems like it could be very ugly. Second is to have a sort of 'clone' method that builds a new immutable object by cloning the old but adding a newly provided set to it (what is this pattern called again?). This gets ugly when I try adding the child most element to the set since I need to pretty much rebuild the entire tree with 'new' immutable objects to add one value.

The third, and so far easiest, solution is to just get rid of the tree structure and make them make a call to my model to get the data they want. so instead of calling myObject.getChildren they call Model.getObjectChildren (myObject). This one will work, but darn it I wanted the pretty tree structure for my immutable state.

Is there some other way to conveniently build up my state in a manner where my Model can freely modify the state while being built; but still have in immutable when it's finally published to the Controller?

ps. I'm running in java if that matters.

1

2 Answers 2

4

I would use interfaces for this:

interface ReadOnlyA {
    public ReadOnlyB getB();
    ...
}

interface ReadOnlyB {
    ...
}

class A implements ReadOnlyA {
    private B b;
    public B getMutableB() {
        return b;
    }
    public ReadOnlyB getB() {
        return getMutableB();
    }
    public void setB(B newB) {
        b = newB;
    }
}

Basically, one interface per class that implements only read-only methods, and returns only instances of the read-only interfaces for other objects; but you use objects of the actual (mutable) classes internally. I believe this is similar to the idea of capabilities --- a reference to the interface is equivalent to a 'read' capability, but your internal references to the classes are 'write' (and 'write contained objects') capabilities.

2
  • +1 for interfaces. This is a good example a problem they were designed to solve. Why not more up votes for this answer? It is certainly better than internal flags. Mar 28, 2013 at 3:47
  • 1
    @mortalapeman: "Better" is relative: Using interfaces this way does not make the object immutable but only the mutating methods inaccessible. There is no way to prevent someone having a reference to the object to cast it to the class A and calling e.g. setB(…). With flags (as described in delnans answer) the object ensures that it is immutable. It would probably be a good idea to combine both methods though, i.e. use a flag to ensure immutability and add a interface to let clients only see relevant methods.
    – siegi
    Apr 19, 2016 at 16:17
6

Sure it is possible. Some even coined a term for it: Popsicle immutable. The general idea is to have a mutable data structure on the inside, plus a flag that tells you whether the object is currently mutable or not. Note that in many cases (including this one), you only want the flag to go from "mutable" to "immutable" once, and never the other way. Then you simply add

  1. Methods to mutate the state, which check the flag and raise an error if the object is not mutable.
  2. A method to flip the flag and thus turn the object immutable. This is also a good opportunity to perform some optimizations (e.g. trim excess capacity of collections or build an index) as you now know the state won't change.

This does add some complexity to the implementation, and some potential for errors (forgetting to flip the switch, trying to mutate an immutable object). But that's inherent to this ability. To regain a bit of simplicity, you can disallow operations not related to building the state while the object is mutable. This means you have fewer cases to support/worry about.

1
  • The robustness of popsicle immunity may be enhanced by having all mutating methods and the "freeze" method confirm that they are on the same thread wherein the object was created, and possibly by having an object keep a "reference for mutation" which is used for all mutating actions. Such an approach would guard against the possibility of any mutations occurring after an object was supposedly "frozen".
    – supercat
    Mar 10, 2014 at 17:32

Not the answer you're looking for? Browse other questions tagged or ask your own question.