Brian Slesinsky's Weblog

Friday, 23 Jul 2004

Single Assignment Considered Error-Prone

Fow a while now, I've been experimenting with concepts from functional programming in Java, immutable objects in particular. Advocates of functional programming claim that it makes programs easier to write, debug, and understand. (See Why Functional Programming Matters.) After getting a bit more experience with it, I'm not so sure about that. Functional programming can be error-prone in its own way.

In particular, a common error I make is to refer to the wrong state when modelling a state machine. Here's a simple example:

  final User user = domain.lookup(userId);
  // lots of code here
  // change the user
  final User next = user.withEmail(newEmail);
  // more code here
  // bug: returned the wrong user state!
  return new Result(user, otherStuff);

The bug comes from having multiple states of an object in scope, all but one of which are obsolete. It becomes very easy to reference the wrong state, particularly when moving lines of code using cut-and-paste. I've tried given them clearer names (like "before" and "after") but that only helps a little.

I think the best solution is to give up on single assignment. Use one mutable variable to keep track of state:

  User user = domain.lookup(userId);
  // lots of code here
  // change the user
  user = user.withEmail(newEmail);
  // the code here can only refer to the last state.
  return new Result(user, otherStuff);

It's clearer and the function is still side-effect free, so what's the harm?

It seems like mixing up states would happen just as easily in pure functional programming languages like Haskell. I wonder what they do? Maybe adding mutable local variables to language like that would be an improvement?