Learning Hack: Meaning vs Representation

During year 0, I was a high school Latin teacher. And, as the saying goes, if I had a nickel for every time I had to defend studying Latin from people who thought it was useless, I could buy a sandwich and maybe some fries. (But that’s like, 200 nickels!)

“Latin’s dead and you’ll never use it!” people would say. True, there are no native speakers of Latin, and the only time I’ve used it professionally I was teaching it, but there’s a huge benefit of translating sentences from one language into another: It forces you to separate meaning from representation.

source: https://xkcd.com/1562/ (license)

If we only study one human language, the sounds we use to represent thoughts and the meaning of those thoughts are very tightly coupled, so we get the impression that meaning and representation highly connected, but there not. We could even argue that (poetry aside), meaning and representation are only accidentally related.

Let’s take integers, for example. 57 is a good integer. In a computer’s memory, it will be represented by some bits, little endian or big endian, or I could write “fifty seven” in English, or I could say it out loud. Not to mention the other human languages, or writing a binary string or a hex string. All these point to the same integer, so we can say they all mean the same thing, but the representations are completely different.

Computer programmers spend a lot of time choosing between different semantically equivalent ways of representing the same idea. Being able to consider meaning and representation separately is a very important skill.

My goal for this post is to put one simple trick in your mental toolbox: You can now explicitly decide whether you are considering the meaning of something, or its representation, or both. Congratulations! Now that you have this trick, what should you do?

I think, first off, you should apply this trick to information hiding. Code that is calling the public methods you write should care about the meaning but not care about the representation. I am writing code that represents a collection of customers with their phone number. The calling code wants to ask a question like “What is Steve’s phone number?” It does not care that you put Steve’s phone number in a Dictionary<Guid, string>, and therefore it should not know. The meaning of the public API you are writing should be able to remain the same while you change the internal representation of your program. What if your database decides to use integers instead of guids as keys? If your client can see the Dictionary<Guid, string> directly, this change might break every piece of code that uses yours. If all the client can see is a method like GetPhoneNumber(string name), the caller does not care if you swap out the internal data structures.

The second place you can use the differences between meaning and representation is in choosing a readable implementation. Let’s look at the following code snippets.

//Part of both snippets:
IEnumerable<Customer> customers = GetCustomers();
private bool MyAwesomePredicate(Customer customer)
{
       //Decide whether customer is awesome.
}
//first snippet:
bool found = false;
foreach(Customer customer in customers)
{
     if(MyAwesomePredicate(customer)
     {
          found = true;
          break;
     }
}
//second snippet:
bool found = customers.Any(MyAwesomePredicate);

//after one snippet or the other runs
if(found)
{
     CelebrateThatCustomersAreAwesome(customers);
}

They both mean essentially the same thing: look at the collection ‘customers’ and if you find a customer that meets the criteria in ‘MyAwesomePredicate’ then celebrate. Yay!

The difference is that in the first snippet, whoever is reading this code later is caught up in the ‘foreach’, that is, in the fact that you’re iterating a collection, not in the question that you’re trying to answer. The representation is more evident than the meaning. In the second example, the meaning is evident; you could almost read the code aloud: “The value found equals ‘do any customers meet MyAwesomePredicate'”.  (Also, thanks to Eric Lippert; the example is based on an old blog post of his, which I can’t find right now, about LINQ.)

This is a pretty simple example, and its also one specific to C#, but it demonstrates the point well: separating meaning from representation allows you to consider which representation best serves the meaning of the code, which allows you to write better code. 

So the next time you’re writing a method, and you have an extra few minutes, try some synonymous ways of writing the method. And ask yourself, first “are these really synonymous?” And if they are, choose the one where the representation provides the fewest barriers to future programmers understanding the meaning.

Till next week, happy learning!

-Will

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s