Sunday, July 25, 2010

Regarding Coding Style Goals

I'm currently creeping my way through a Javascript book. It's taking longer than I would like since it's not high enough on my priority list at the moment, and because it's summer. In the interest of keeping things rolling, I thought I might write about code aesthetics today. Everyone who programs has a slightly different preferred coding style. Here are a few of the things that I love to see when reading code and strive to do when writing it. Take a moment and think about general coding practices you like. Now you can be amused by how similar, or different, our priorities are.

When I'm reading code, I love seeing things that improve my ability to grasp both what the code is doing and where that piece fits in the larger whole. Descriptive naming is a huge help, and it goes beyond just what you call your functions and variables. I enjoy seeing complex Boolean tests broken into logical parts using descriptive Boolean variables. Meaningful constants in place of literals, especially numeric literals, are a joy to read.  Naming in libraries can help their users understand not what they are but their focus as well. Whether I prefer seeing a pattern like FileOpenFileRead, and FileClose to OpenFileReadFile, and CloseFile in a function library depends on what the library is for. The naming should reflect the usage pattern. If the library is focused on file I/O, I like the File part first. If it's a generic I/O library that provides similar operations across a large type of targets, put the operation name first and the File/Socket/PrintBuffer part next. I usually name GUI widget variables using the style of typePurpose, resulting in names such as labelTitle, and buttonStartCountdown, to make them easier to find both in graphical designers and the code. Similarly, I like to reflect class hierarchies in their naming. For example, think about an abstract socket class and two concrete subclasses implementing UDP and TCP sockets. I prefer the naming to help me see not just what the classes represent, but their relationships too. So, I wouldn't call them AbsSocketTcpSocket, and UdpSocket. Instead, I'd call them SocketSocketTcp, and SocketUdp, or something along those lines. Note the effects on auto-completion with this scheme: typing the base class will give you the subclasses because the name directly reflects the inheritance relationship.  And you can't talk about clarity without mentioning comments. Comments that tell why something is being done the way it is are often more important than comments that tell what is being done. And of course, misleading, incorrect, and out of date comments can quickly destroy your code's clarity.

Having similar things work similarly seems obvious, but I'm sure you've seen code that just doesn't do it. If the existing methods in a class report errors by throwing an exception, I don't want to add a new method that uses a return code, and vice versa. I like seeing consistent parameter ordering in related routines. Using I/O library example from above, I'm going to be much happier if all of the routines take their target identifier in the same relative position in the parameter lists than if some of them have it first, others last, and a few somewhere in between.

Having, and enforcing, coding style conventions is a big deal. They help keep you reading code rather than having to stop and check if the indention is misleading or if there is some significance to that one variable using underscores instead of being camel cased. And I doubt anyone likes having to change their editor's tab/indention settings every time they change what they are working on. It's just one more niggling little thing to forget. Personally, I'm a huge advocate of the generic conventions put forth in the second edition of Code Complete. To paraphrase a recent political slogan, yes we can use the same coding style across all languages.

Simplicity is a big pet peeve of mine. The KISS rule has real benefits. Writing working code is hard enough when you can keep the model in your head, and my memory is poor enough that I really hate extraneous noise. I strive to keep the noise down when I can with these personal rules. Avoid routines that do nothing but call one other routine, they can be an indication of poor design. (Language specific things such as compiler chaining and faking default parameters get a pass on this. Sometimes.) Don't create a whole new class when a method will do. An abstract class with only one subclass wastes programmer and compiler time. Really think hard about inheritance. Using true subtypes should reduce the complexity of the code. If it isn't, I may be coming at it from the wrong angle. Would composition be a better fit than inheritance? Can I use conditional statements instead, or will that cause me headaches later? Write classes/routines for specific tasks unless you already have a concrete reason for them to be more generic. Try to keep paths between where data is stored and where it is used as short as possible (ideally this would be handled within a single class/set of routines).

I tend not to follow this rule in my writing, but I do try to in my coding. The less code there is, the fewer places you have to check later to find defects. I try to follow the DRY rule. Comments that just restate code are always annoying. Plus, I have a pathological hatred of redundant header comments. (Why do I need to write the name of the routine in a comment right above the syntactic definition of that name!) Brevity speaks to design in a very similar way as simplicity, for instance not adding a transformation layer to code when you can correct the data differences to not require the transformation in the first place. It's worth noting that as code ages, it gets harder and harder to maintain brevity in the face of normal development accretion.

There are real tradeoffs between these goals, and in general I have listed them in my order of preference. I'd rather the code be clear than brief, and prefer consistent to simple. Striving for all of them at once is one of the things that makes programming fun (and frustrating). Actually achieving them all produces what a colleague once referred to as really sexy code.

Sunday, July 18, 2010

A Strategy for Strategy

The summer heat and humidity settled across the area early and in force this year.  June was the hottest June on record, ever, and July's temps are staying above normal so far.  Paradoxically, when the sun is bright in the summer, I tend to close up my south facing blinds more often in an attempt to keep the house cooler.  And if it's going to be cool and relatively dim in the house, well that's a perfect video gaming setup.

I've been anticipating Starcraft 2 for some time, despite having "finished" with the real-time strategy genre in the late 90's.  In many ways, the game is a throwback to the decade old original, which was in turn a mere evolutionary step above its even older predecessors.  That said, there is one new "killer" feature that has hooked my interest almost more than the game itself: replays.  Starcraft 2 automatically records every game you play.  You can then play it back anytime for review and analysis or upload it to the internet for others to examine.  I think it will be a revolution in analyzing ones own play.  Of course, the serious Starcraft community has been analyzing matches for quite a while.  One such commentator has taken the place of physical sports for me this summer.  His name is Sean Plott, his handle is Day[9], and the archives of his commentary can be found here.  Be warned, his enthusiasm for the game is infectious.  (Though like sports, there is a fair amount of shorthand jargon you may have a hard time immediately understanding if you aren't at least passingly familiar with the game.)  One cast, covering some basics of developing Starcraft strategy, really caught my attention.  I think the things he mentioned are widely applicable across all sorts of different strategy games, and I want to go into them here for a bit.  Honestly, I think there may be some aspects to the tips that can be applied to life in general as well.

Have a plan.
Seems obvious, right?  But really, the root of any sound strategy begins with an attempt to accomplish something.  You may succeed by acting randomly in the moment, but you won't know why, and you won't be able to reproduce your success consistently.  Come up with a means to get to your desired end.  It shouldn't be too rigid in the face of adversity, but neither should you abandon it at the first sign of trouble.

It's more about timing than speed.
Just because you are constantly doing things doesn't mean you are actually moving efficiently.  Having good timing means you can outpace competitors who are fast but not as good at using resources properly.  (And how many of us wish we could get that message through in our workplaces?)  Remember the lesson of the tortoise and the hare, and keep an eye on speed vs. quality trade-offs.

Remembering what you need to do is the key to good timing.
Sean recommends building a mental list of the things you need to constantly keep track of as you go about executing your plan.  Then just loop through the list over and over.  At each step make sure you have it covered and then move on to the next.  As the number of things you have to keep track of increases, so does your list.  This list becomes a tool to leverage repetition for learning.  With practice, the "simple/mechanical/housekeeping" stuff becomes internalized and you can focus your mental energy on the "big picture."

Don't think about what you are doing now, think about what you need to do next.
Now is already happening, stick to your list and you don't have to worry about it.  Given the situation, what do you need to do next to keep moving along your plan?  This is where your flexibility lies.  If you loose a battle in Starcraft or get your queen captured in chess, don't sit in the moment fretting about how it happened, use your list to keep moving forward and get straight into mitigation if you need to.

Improve your technique as you go.
Practice had to come in here at some point, and this is it.  You have to learn your sense of timing through focused effort.  The first step is to thoroughly learn your game's mechanics.  For a real-time game like Starcraft 2, this will also involve training your physical memory for the interface, which is the same thing one does when practicing a musical instrument or learning an artistic medium.  Games like chess or go lend themselves toward learning to intuitively see patterns developing on the board.

I want to give a big thanks to Sean for framing the bolded tips above.  I suspect I will be pondering their application in all sorts of areas for some time to come.  And when you think about it, they make a pretty good mental list in and of themselves, don't they?

Thursday, July 15, 2010

OK, It's Over Now. Old Spice Wins the Internet (at least this week)

Yes, I've posted a pair of Old Spice ads just because I find them hilarious.  It turns out that they are more than just hilarious, they are quite savvy.  Here's one story about it.  I promise I will not post anything else about it.  Besides, you should be watching hilariously silly videos rather than reading my magnificent words.

Sunday, July 11, 2010

Headline Hunting

It's been a while since a headline jumped out at me, but happily the BBC comes to the rescue.  And once again, the headline on the story is different from the one that showed up in the RSS reader.  Yes, "Body part scare on motorway proves 'armless" is less informative than "Plastic arm on M62 in Mercyside causes 'traffic chaos,'" but the original is just gold!

Monday, July 5, 2010

I Smell Awesome, Again

The man your man could smell like is back in action again, and it's another winner.  Yes, I'm posting someone else's commercial without them paying me.  Heck, I even went out and got some of the endorsed product (which turned out to be quite good).  Bringing the funny should be rewarded, darn it!