What’s so good about immutability?

When I first started learning functional programming, immutability was one of the great looming walls which I encountered.  I kept looking for some deep and complex reason that variables shouldn’t mutate, when in fact, the reason is very, very simple.  Immutable variables make code more predictable.

Let’s say you and I, and ten others are seated in a circle.  You need to pass a message to everyone, but you can’t do it by speaking.  “Aha,” you declare.  “I’ll write a note, and everyone can pass it down!”  If I asked you at this point whether you’d like the note laminated, what would your response be?

My guess is, you’d answer, “No, thanks.  It’s just going around the circle.”  Seems pretty reasonable, when you’re just making sure 11 people get the same message, especially if you know and trust them.  What if you needed to pass the note to a thousand people, or ten thousand?  The note might get ripped, smudged, or some troll might deliberately change it.

Laminating the message ensures that everyone gets the same message, and that is where immutability becomes powerful.  Know what the difference is between this:

var message = "This is a message.";
logger.Log(message);
var messageInQuotes = "\"" + message + "\"";

and this?

let message = "This is a message."
logger.Log message
let messageInQuotes = "\"" + message + "\""

The difference is that we can only predict the value of messageInQuotes in the second code example.  In the C# example, once the message variable is passed into the Log method, you are allowing it or any methods it calls to change the state of the message.  With immutable variables, you can predict the state of messageInQuotes.

This may not seem earth-shaking or profound, and that’s because it isn’t.  Like the best things in programming, it’s incredibly simple.  If you’re writing a ten-line console app, who cares about mutability?  When you’re working with ten-million lines of code, event-driven asynchronous processing, and multi-threading (or as I like to call it, enterprise development), you might want to care. 

Going back to our analogy of ten-thousand people all getting the same message, you don’t have to assume there’s a bad egg.  People make mistakes all the time.  Maybe the message was, “There’s a party on Fulton St,” and someone thought, “I don’t know a Fulton St.  You must have meant Fuller St.  I’ll fix it for you and pass it on.”  Only with software, it’s that one errant function.

I’m not trying to say that C# is bad, or that F# is better.  Both C# and F# offer mutability and immutability.  With any language, enterprise-scale development is complicated and complexity reduces predictability, which in turn reduces reliability.  Immutability can help your code to be more predictable, and (IMHO) more readable. 

In closing, look at the following code.  Assuming we want to get the reversed value of an original string, is it clearer to pass the string to a function which will reverse it, or to pass it into a method which will return the reversed value and then assign that value to a new variable?

// relying on mutability
public void ReverseString(string forwards)
{
var chars = forwards.ToCharArray();
Array.Reverse(chars);
forwards = new String(chars);
}
ReverseString(message);
// immutable implementation
public string ReverseString(string forwards)
{
var chars = forwards.ToCharArray();
var reversedChars = chars.Reverse().ToArray();
return new String(reversedChars);
}
reversedMessage = ReverseString(message);

Something put between the foot and the shoe.

Since my very first app in C#, I’ve felt a bit like an, admittedly boring, non-conformist.  It started at DeVry with the traditional Hello World project, for which I received a whopping 0 of 100.  When I asked the professor how on earth a functioning program which fully matched the project requirements could be a complete failure, the professor explained that I failed for not having comments.

Apparently, the following program is so vastly complicated as to be incomprehensible without the accompanying green text.

public static void Main(string[] args)
{
// Writes "Hello World" to the console.
Console.WriteLine("Hello World");
}

Now the professor, you, and I all know that the comment doesn’t really help in this case.  What’s important is, it reinforces the good habit of commenting your code.  Really though, how good a habit is it?

One of my favorite stories from the excellent show QI, is the line about Samuel Johnson’s definition for, “sock.”  You guessed it, “Something put between the foot and the shoe.”  Astonishing in it’s clarity, right?  Imagine you have no idea what a sock is.  How many possible items could it be?  What material is used to make it?  Most importantly, why are you putting it between the foot and the shoe?!

Without knowing what purpose the object serves, how are we to use it correctly?  Yet, I consistently see definitions such as this in comments, or worse yet, the dreaded:

/// <summary>
/// Sock
/// </summary>
public Sock Sock { get; set; }
view raw SimpleSock.cs hosted with ❤ by GitHub

Surely you jest!  You mean to say that a property of type Sock, which you have named “Sock”, is a… Sock?!  No!

So what’s my point?  Not everyone’s a wordsmith.  Too true.  I struggle with comments all the time.  My point is that we need to stop teaching new developers to mindlessly shove green text in their code.  Where code and comments fail to add value, they reduce value.  Every line read which does not enhance understanding, is a delay and a distraction on the path to grokking the solution.

If you can’t find a better descriptor for your field/property/method than the name itself, don’t bother putting in a comment.  It just takes up space on your and my screen.

That said, try to leave useful comments which add value.  If you’re using a little-known class, or a hot new open-source library, add a link to a good tutorial or the github page.  Give the next guy a resource.  If you can’t think of a way to add clarity to a property declaration, work on something else.  Grab a coffee.  Come back to it when the code is stale enough in your own mind that you can see what I’ll see.  That would be the giant, “What in the Sam Hill is a Metaphor<string>?

Most of all, if the comment won’t add value, don’t write it.  Comments aren’t there to please the professor, or Ms. Manners, or the standards committee.  They’re there to help the next developer use your awesome tool.  Oh, and remember, Dr. Johnson was a brilliant scholar.  Even his definitions weren’t always perfect.

On a final note, I leave you my definition of a sock:

/// <summary>
/// A cloth sleeve which protects and insulates a foot.
/// </summary>
/// <remarks>
/// A sock is generally a cloth tube with only one open
/// end. It is worn over the foot and can help to keep
/// the foot warm in cold weather, as well as prevent
/// chafing when worn between the foot and a shoe, boot
/// or similar garment.
/// </remarks>
/// <example>
/// This shows the basic use of a sock. Please remember,
/// the sock is worn over the foot and under the shoe.
/// <code>
/// class Foot
/// {
/// public Sneakers Shoes { get; set; }
/// public Socks Socks { get; set; }
///
/// public void DonShoes()
/// {
/// this.DonSocks(this.Socks);
/// this.ShoesWorn = true;
/// }
///
/// public void DoffShoes()
/// {
/// this.DoffSocks(this.Socks);
/// this.ShoesWorn = false;
/// }
/// }
/// </code>
/// </example>
public class Sock
{
}
view raw MySock.cs hosted with ❤ by GitHub