5

I know immutable objects are preferred to mutable objects for reasoning and maintenance. But in occasions making a class immutable have some costs, let me explain it with a simple example:

class Mutable  
{
    private int i;
    public Mutable(int _i) { i = _i}
    public void Print() // impure function
    {
         print(i);
         i++;   // logic inside
    }
}

... caller

Immutable m = new Mutable(1);
while (true)
{        
    m.Print();
}

I call it mutable because its internal state changes and Print varies on each call.

Versus.

class Immutable  
{
    private int i;
    public Mutable(int _i) { i = _i}
    public int Print() // pure function
    {
         print(i);
         return i;  // returns its state  
    }
}

... caller
int i =1;
while (true)
{
    Immutable im = new Immutable(i);
    i = im.Print(); // get the previous obeject's state
    i++; // logic outside
}

Preferring immutable solution make me to do a lot of work outside of an object which was supposed to encapsulate that logic.


My actual problem (you may skip the example below)

I have a class which draws a text in a box:

class TextDrawer
{
   private string text;
   private Rectangle box;
   public TextDrawer(_text, _box) {...}
   public void DrawTextInBox()
   {
   }
}

It is probable that the Text overflows from the box and part of it wasn't written. I should know the remaining unwritten part to draw it in a new box.(in fact I take an snapshot of the old box as a video frame and need to make a new frame for the remaining text to make a video of the text)

Now I have two options:

1- Make the TextDrawer mutable (its internal state is mutable) and DrawTextInBox a non-pure function and on each call it draws the remaining part of text in the box.

class TextDrawer
{

   private string text;
   private Rectangle box;
   private string remaining;   

   public TextDrawer(_text, _box)
   {
      remaining = text = _text;
      box = _box;
   }    
   public void DrawTextInBox()
   {
      draw as you can from remaining
      update remaining part;
   }
}

2- Keep the TextDrawer immutable and DrawTextInBox a pure function which returns the remaining part, then the caller should keep track of the remaining and pass it again to the TextDrawer or instantiate a new TextDrawer by the remaining text until there is nothing to write.

class TextDrawer
{
   private string text;
   private Rectangle box;
   public TextDrawer(_text, _box) { ... }
   public string DrawTextInBox()
   {
       draw as you can from text;
       return remaining part;
   }
}

The second approach is immutable but actually shifts the responsibility of tracking the remaining part outside of the class. The first approach is mutable, but it encapsulates the logic and just need a call to DrawTextInBox to draw the remaining part.


Question: The logic of the above examples was simple but this logic could be more complex, then I don't know whether to extract this logic from a class in order to make it immutable or let it be mutable and have the logic inside?

  • 1
    In both cases, TextDrawer has settable properties, so in neither case is TextDrawer immutable. Also, even if TextDrawer had no settable properties, still, RECT is mutable, therefore any class containing a RECT is also mutable. Perhaps you are missing something with respect to what immutable means? – Mike Nakis Apr 14 '15 at 12:48
  • @MikeNakis We should assume RECT is immutable for the sake of argument. However, you're right about being able to assign these properties causing TextDrawer to not be immutable. – Neil Apr 14 '15 at 12:54
  • @MikeNakis I made both properties private, they just can be passed to the constructor, but the point still remains. – Ahmad Apr 14 '15 at 14:09
  • The second approach is immutable but actually shifts the responsibility of updating the remaining part outside of the class. I don't get this statement. With both options you have to make a second call to DrawTextInBox to draw the remaining part. The only difference is whether the remaining part is kept internally or returned explicitly. – Doval Apr 14 '15 at 14:33
  • @Doval, maybe my understanding of immutability is incorrect, I think in the second approach the internal state of the object changes, so the DrawTextInBox is not pure and calling it each time makes a different result.(Am I correct?) anyway it is something I don't like about an object, what is called? – Ahmad Apr 14 '15 at 14:43
3

In your example:

int i =1;
while (true)
{
    Immutable im = new Immutable(i);
    i = im.Print(); // get the previous obeject's state
    i++; // logic outside
}

Immutable should return the new state that the mutable solution would've stored, i.e. i + 1. You already have the old state. Returning the old state and forcing the caller to update the state himself is pointless. You did this correctly in your real problem, where you return the remaining part of the string instead of the original string.

You should prefer an immutable solution unless you have good reasons otherwise. A good reason may be that the immutable solution is too slow, but first you have to clearly define what's "fast enough" and profile the application to show that the bottleneck is your immutable class and that the mutable alternative will solve the problem.

  • You are right my example differs with the actual problem. if we call i state, Immutable should return i+1 and the difference is performance; But if I call it logic, it is something that Mutable does it internally but Immutable doesn't care. Preferring immutable solution make me to do a lot of work outside of an object which was supposed to encapsulate that logic. You can regard the Mutable a counter or a timer, they are good objects, not?! (Just I doubt!) – Ahmad Apr 14 '15 at 16:25
  • Or maybe you mean that the right way is instead of updating the state inside the object, I should always update the state and return it in an Immutable solution. That makes sense!! – Ahmad Apr 14 '15 at 16:34
  • 1
    You should prefer an immutable solution -- As part of a UI? UI's are naturally mutable... Is it your position that a textbox object be replaced with a new textbox object every time some property on the textbox changes? – Robert Harvey Apr 14 '15 at 16:37
  • @RobertHarvey He asked a broad question, I gave him a broad answer. You can always compute the new state that the UI will present in a purely functional way (not necessarily as efficiently, and your language of choice may make this awkward.) For the particular problem Ahmad gave I don't see any difficulty. He's just sequentially transforming and presenting some state. Returning the new state makes the transformation more obvious, and has less chance of causing trouble if two references to the same TextDrawer ever exist. Anyways, I used "prefer" precisely because there are exceptions. – Doval Apr 14 '15 at 16:52
  • 2
    The goal of functional programming isn't to disallow mutability, it is to make mutability explicit (paraphrased quote). Likewise, functional program doesn't try to hide the steps involved in rendering a textbox - it tries to expose the steps so that the caller can have very fine grained control. In this question, the steps involve first computing the word bounding boxes from the string, checking that against the boundary, then compute the wrapping. A functional programming approach will expose those steps to the caller. Now you can see places where immutability can / cannot apply. – rwong Apr 14 '15 at 17:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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