≡ Menu

Source Code is Not Plain Text

Earlier today I was looking back through my old blog for some specific info, and I found an entry called ‘Source Code is Not Plain Text’ that I really enjoyed writing. I often cringe when re-reading or re-playing something I developed years ago, but I had a lot of fun checking this one out again – so I decided to repost it here. Hopefully you get something out of it. The text is unchanged from the original, I fought the urge to rewrite some parts.

This is what I started programming in:

I soon graduated to this:

Sometimes I messed around in this:

Turbo Pascal IDE Screenshot

Then I moved onto this:

Visual C++ 6 IDE Screenshot

Today I develop in something that looks like this:

Visual Studio 2010 IDE Screenshot

Some people prefer this one:

Eclipse IDE Screenshot

Times sure have changed, huh? I mean look at all of those sweet menus and pretty colors. Programming is no longer a world of blue backgrounds and white text, but instead a consistently integrated set of Windows-themed forms. Instead of just a screen full of a single source file we’ve got Solution Explorers, Property Windows, and an ever-shrinking amount of screen real estate for actual code. Thankfully monitor resolution has increased dramatically or we’d all be coding within a two-inch by three-inch rectangle by now.

So the front end has obviously changed, but what about the end result? The output of everything that I do is still just some text that gets compiled into 1s and 0s and eventually turned into pretty pictures by a bunch of low level technology that I don’t know anything about. Right? This might all technically be true – but I’m pretty sure it is not the correct way to think about the product of all the work that we put into our various IDEs.

As with most things in life, there are a bunch of different ways to look at our program.

Here’s one way:

Image of C++ Code

Here’s another:

Image of a Generic UML Diagram

Here’s another:

DOOM Screenshot

When we’re programming, we’re not really manipulating text. We’re dealing with much higher level concepts. The text that we type is just one representation of our program. It’s a valid one for sure, but not intrinsically an especially valid one.

Looking at the three pictures above, it’s tough to say which one is closest to the typical mindset that I have as I work on code. Most of the time it’s some blend of these three, but my mental model of the project I’m working on definitely slides and adjusts depending on the specifics of what exactly I’m engaged in.

Everything starts out with the picture number three. The user experience is everything. All of the code I write and systems I engineer are assembled with the intention of presenting some experience or idea to the player. This is something that is easy to lose track of as a programmer, and I really work hard to keep everything flowing from the user experience.

As a project moves into any sort of system or code architecture/design phase, my view shifts towards picture number two. Instead of polygons or text, I see abstract objects and their various relationships. Low-level specifics are not as important as the system’s realistic validity. This is also the world I live in during design meetings, playthroughs, test sessions, etc. It’s always very important to place the user experience up on a pedestal, but as the technical representative in many of these meetings it’s my number one responsibility to inform others of the systemic validity of ideas and proposals.

When I finally sit down to actually implement something then I move up into the first picture, always trying to keep the other two in my mind. Even while operating on this level, there are some definite traps that we can fall into by thinking about our code as text instead of something more sophisticated. Here’s one example:

Say I have a function that looks like this:

float Player::TakeDamage(float amount, bool poisonDamage)
{
   m_health -= amount;
   if (poisonDamage == true)
   {
      m_poisoned = true;
   }
   return m_health;
}

… and then I decide to remove the concept of a player being poisoned from my game. What a pain in the ass, huh? You might be thinking, “Well that’s what you get for implementing poison like that!” and you might be right, but stick with me for now – it’s just an example.

Here’s one way to fix this:

  • Remove “, bool poisonDamage” from the Player::TakeDamage().
  • Remove the m_poisoned member variable from the Player class.
  • Do a find in files for “TakeDamage”.
  • Go down this list and remove the poisonDamage parameter from each found function call.
  • Attempt a compile and probably get a few errors.
  • Delete all local variables, data lookups, etc. that were feeding into the poisonDamage parameter.
  • Compile and run.

This strategy is a result of treating your source code as just a bunch of text files. Here’s another way that we could solve this problem.

  • Right-click on the TakeDamage function and choose “Refactor -> Change Signature”.
  • Remove the boolean poisonDamage parameter.
  • Attempt a compile and probably get a few errors.
  • Delete all local variables, data lookups, etc. that were feeding into the poisonDamage parameter.
  • Compile and run.

How different are these two things? In one we did a bunch of text searching to track down the information that we needed to change. In the other we relied on our IDE’s higher-level knowledge of our program to streamline (at least part of) our change. The second method isn’t going to save you a day of work in this example, but it will certainly save you some work.

The important point here is the way that we think about our code. When we have this line in our program:

float Player::TakeDamage(float amount, bool poisonDamage)

This is not just a bit of text. It’s conceptualizing a whole bunch of stuff. It’s a function that’s designed to be called in a certain way. It has specific inputs and outputs. It does certain work. This is all information that your IDE and refactoring tools have at their disposal. When operating on (or with) this function, it only makes sense to deal with it as a higher-level concept instead of just a bit of text.

IntelliSense is the most obvious opportunity that the average Visual Studio developer has to take advantage of the IDE’s meta-view of their program. Earlier in my life I thought that Visual Studio was just filling in text for me, and this is definitely the wrong view to have of this feature. IntelliSense is using structural information about your code to turn your text prompts into a proposed set of complete function names, variables, or parameters.

When you type in something line this:

mStorage.push_back(hit

… and then stop, IntelliSense is able to look at the function you’re in, the class you’re dealing with, and a bunch of other things to figure out that you must mean to push_back() either hitObjectInstigator or hitObjectReceiver. When you’re prompted to choose one of these two to complete your function call, you’re not in the land of auto-completing text, you’re in the land of filling out your function call based on selecting one of two different concepts that exist in and around the code you’re editing. This work is not just simple auto-completion.

Anyway, that’s how I think about it. On the other hand, there are people who still use “developed in Notepad” as a point of pride. This is something that I do not understand at all. On a somewhat less-crazy scale, there are plenty of programmers I’ve met who don’t like IntelliSense or Visual Assist out of some strange desire to be “close to the code” that I don’t really understand. As far as I can tell this mainly involves looking up a lot of function names while devoting a whole bunch of brain space towards memorizing parameter lists. Personally, I need all of the brain power that I have to solve actual problems.

There are a bunch of refactoring and general workflow tools available beyond IntelliSense. Here are links to two common ones:

Visual Assist
Resharper

In my experience, the refactoring options available in C# with Resharper definitely one-up the refactoring options available in C++ with Visual Assist – mostly due to the intrinsic limitations of the language.

{ 2 comments… add one }

  • Ian January 28, 2011, 1:36 pm

    Believe it or not, I actually understood this. And I found it fascinating. (I attribute this to your writing skill, and not my brain.)

    Anyway, I end up doing a lot of writing and a lot of production: our school’s annual magazine, for instance, is pretty much done 100% by me. The point is that I end up looking at piles of text that need to be molded into a magazine, and I wish there was some sort of meta-aware development tool that I could use for more wishy washy concepts like branding. Strings of text in stories are oftentimes ideas that could be analogous to functions that are either strengthening or weakening our brand.

    Maybe this is silly, but your post gave me a better schema for thinking about my copywriting. Plus, there probably is some software out there that could help me. Thanks!

  • Steve January 28, 2011, 2:49 pm

    A concept that’s slightly lower level than what I wrote about here that I find super useful to think about is called primitive obsession.

    Basically this is the tendency for programmers to use primitive data types to represent concepts when they really should be using more higher-level structure. For example, let’s say you need to represent a file name in code. You can just use a string “C:\test.txt”, and that works – but it’s probably not the best way to think about your problem. Instead of using a totally generic, primitive data type like string, you should make a higher level ‘FileName’ class/structure with functionality that you will likely want to have when working with filenames (strip out the path, get the extension/type, find the root directory, whatever).

    Just because you can use a simple string to represent a filename doesn’t mean that you should. It’s not a string, it’s a filename! And also, just because you can represent something as simple plain text doesn’t mean that you should. It’s very likely that there’s a more useful abstraction. I have another blog post that I wrote about this, I’ll dig it up sometime this weekend and post it… it’s really generally useful stuff.

Leave a Comment