Et in Arcadia Ego 10¢ Contact
 
« Four Kinds of Stuck
Mentons: What the Brain Runs On »

Keep Taking Steps Forward

By Jeff | Published: October 17, 2011

In the last couple of posts I’ve talked about a programmer’s greatest enemy: getting stuck. I talked about the various levels of how stuck you can get, from getting stuck while trudging through documentation to getting stuck because you don’t have the resources—passwords, files—that you need to perform a task.

This leads me to my ultimate advice for how to avoid getting stuck and how to get unstuck.

The secret to getting and staying unstuck is to keeping taking steps forward. Simple as that sounds, it is more difficult than it seems, and many programmers never master it.

In order to keep taking steps forward you first have to know what forward is. What are you trying to accomplish? What’s the real task? Tragically, programmers often get stuck on tasks that aren’t really even what they’re supposed to be doing—aren’t even really all that valuable. When you’re chasing down a bug in a tool that’s meant to help you find an optimization for a class that you’re trying to fix in order to solve a user experience complaint, it’s easy to forget that the user experience complaint is your true task, not the bug in the tool.

From what I’ve observed, programmers, in general, tend to obsess. We like to dive down into the nitty-gritty of things. And we tend to get distracted, entranced by the pretty pixels on screen, the annoying obstacles, the intriguing puzzles that programming throws our way. Pretty soon, we’re pulling our hair out over a problem that doesn’t even matter.

This seems to happen to me whenever I use awk. Awk is a small programming language that lets you manipulate text easily within Unix. I often use it to manipulate groups of files. Say, for example, I’ve got a folder full of images. I want to rename all of the images so that each name has an ascending number at the end. Awk is great at this kind of thing. You can write a simple, two-line awk program to read the file names, keep a tally, append the tally number to the filename, and then direct the renaming.

But I don’t know awk that well. So whenever I want to write an awk program, I have to go back to the documentation, study up again a little bit, and then experiment with solutions. Pretty soon I’m debugging some archaic little piece of awk code that won’t quite do what I want. Two hours later I remember, “Oh yeah, I was really just wanting to rename these files. I suppose I could just rename them by hand….”

To avoid getting stuck, you’ve got to remember which way is forward. So before launching off on a long Google search or a marathon debugging session, ask yourself, “What am I really working on today? Is this long, arduous sub-sub-task really essential to what I need to accomplish?” Often, it’s not. And when it’s not, pull up. Get clear, Wedge. You can’t do any more good back there. Go back to focusing on what is truly crucial.

Once you know what forward is, then you can take steps forward. A step forward is an action that actually moves toward resolving the problem. It’s not just a step. It’s a step forward.

One example of this is in debugging. I see lots of programmers go round and around for hours chasing down a single bug. They tell themselves that they’re spending hours because the bug is really difficult. But then a stronger programmer comes along and fixes the bug in minutes. Ouch.

What’s the difference between the junior programmer who spends hours and the master who spends minutes? The difference is that a master debugger knows how to make a strong, positive step every time he or she runs the program.

Many programmers debug by guessing, dabbling with the code, then running the application to see what their dabbling did. Two hundred iterations of dabbling later, they’re still searching for the problem.

The master programer doesn’t dabble. Each step is a clear, targeted, incisive experiment to test a particular hypothesis about what is causing the bug.

The junior programmer performs an O(n) algorithm. Make a random guess. Test it. Make another random guess. Test it. Follow your intuition. Use your instincts. Go with the flow.

This particular kind of flow leads straight to stuck.

The master programmer performs an O(logn) algorithm at worst. At worst, each experiment invalidates half of the possible causes. Some experiments, thoughtfully chosen, eliminate a much larger swath. Therefore even if there are millions of possible causes for the bug—millions of lines of code—the tests must ultimately converge somewhere. And they will do so in a relatively small number of steps.

Always take steps forward, not just around.

Finally, take clear, distinct steps. Programmers often work on intuition, and that’s great. Intuitions about what classes to write, what functions to implement, whether a variable should be an int or an unsigned int or a char. Intuitions are fine, and not every intuition has to be rigorously examined.

But when you’re faced with a big problem that can cost you hours out of your life, you need more than intuition. You need clear, distinct progress. You need discrete steps that enable you to see whether you’re moving forward, backward, or not at all.

When I’m debugging a big bug, for example, I tend to write down each step in the debugging process. Here, for example, are some notes from a bug I fixed earlier this year. They won’t mean a whole lot to you—it was a crash caused by a bug in a smart pointer class I had written—but it will give you a sense for the kinds of notes I take. Each line represents a finding that I documented after performing a round of hypothesizing and testing.

Occurs in Object::Release(). Assertion failure. The problem is that m_nReferences is 0 when the function is called.

The function is called in this case by ObjectSingleton< AssetManager>::~ObjectSingleton(), which nullifies the s_pInstance smart pointer, which calls Release().

The destructor is called, ironically, by Object::Release(), again where this == the asset manager.

So in other words, the asset manager’s release function is called, bringing the ref count to 0, which causes the object to be deleted, which causes the self-pointer to be set to 0, which causes Release() to be called again.

I’m not sure yet whether this data describes the whole problem or if there is more to look at (e.g. why is the first Object::Release() called?). But let’s look at what we have so far….

About 2-3 minutes passed between each of those lines. Those minutes were filled with setting up a test, then quickly compiling and running the code to confirm the results of the test. By writing down my findings after each step, I was made more conscious of the actions I was taking and how to keep moving forward. I had a handy log of where I had been so that I wasn’t tempted to backtrack. And by turning my thoughts into sentences I made sure I knew what I was doing and why.

Intuition is great, but it tends to drift around. Drifting isn’t good for making progress. To avoid getting stuck, I corral my intuition with notes. And it really helps. Even the severe bugs that used to take me days now take at most hours. And it’s a rare bug that’s that severe. When I take discrete steps forward, few bugs take more than a few minutes to find and fix.

I’ve been talking about debugging as an example of taking clear, forward steps. But I find that these ideas apply in any kind of programming task. Whether it’s designing a class, working out a new algorithm, publishing an app to the App Store, or even reading through API documentation, knowing what forward is, and then taking clear steps that forcefully move you forward is the greatest antidote to getting stuck.

If you want to minimize the stuckness in your life as a programmer, make sure you know what “forward” is, then keep taking steps in that direction.

Be Sociable, Share!
  • Tweet
This entry was posted in productivity, programming, thinking. Bookmark the permalink. Post a comment or leave a trackback: Trackback URL.
« Four Kinds of Stuck
Mentons: What the Brain Runs On »

9 Comments

  1. Jaime Herazo
    Posted October 17, 2011 at 10:27 am | Permalink

    You just described The X-Y Problem. A real bane in help channels, and one you’ll always keep falling into on a regular basis :)

    Reply
    • Jeff
      Posted October 17, 2011 at 11:06 am | Permalink

      Yes—that’s very much along the same lines, and an article well worth reading.

      Reply
  2. LVD
    Posted October 17, 2011 at 11:02 am | Permalink

    It’s 10 am and I’m just about to go to bed after 72 hours of straight coding. I was STUCK trying to get another team’s wonderful web service client code generator work to create a client to call a web service I could have manually created in a a fraction of the time (which is exactly what I ended up doing). Granted, their generated code comes with all sorts of automated logging, schema validation at every step, automatic handling of async methods, etc. But I didn’t need any of that functionality and just needed to create a simple WS and a client for it (sadly in COM to be consumed by a C++ legacy app, which I also made the changes to).

    To make things worse, my management team had met up with the other team and been completely seduced by their fancy powerpoint presentations on this code generator and are now hellbent on using it…

    I saw this article as I got home and getting ready to go to bed. Ironic considering the timing and equally enlightening.

    I guess on some level we all know all this, we know we’re avoiding taking steps forward because we’re dreading the mere possibility of getting stuck.We know the other team’s code vulgarity is only surpassed by their almost non-existant documentation, we know we’re not moving forward and there’s somewhere else we should be/something else we should be doing, but actually, consciously knowing it and acknowledging that knowledge really makes the difference in moving forward.

    Thank you very much Jeff for the great article and reminding us all!!a

    Reply
    • Jeff
      Posted October 17, 2011 at 11:04 am | Permalink

      You’re welcome, thank you for the case study, and I hope it gets better!

      Reply
  3. Aiden Bram
    Posted October 17, 2011 at 8:48 pm | Permalink

    This isn’t really about programming, is it. Thanks for the great article!

    Reply
    • Jeff
      Posted October 18, 2011 at 6:55 am | Permalink

      Hmm. I suppose it could be applied to just about anything. I was just thinking of programming because that’s where I have to work at applying these concepts.

      Reply
  4. Jorijn Schrijvershof
    Posted October 18, 2011 at 1:03 am | Permalink

    I enjoyed reading this and this might just keep me from fiddling with useless problems in the near future. Thank you.

    Reply
  5. Jonathan Hogg
    Posted October 18, 2011 at 11:09 am | Permalink

    Thanks for this! It’s just so good to hear that some of those things I accuse myself of are likely part and parcel to programming–the OCD, the side-tracking on perfecting debug tools (why settle for a hash key/value dump when it could be recursive in case you had values that were themselves hashes…), that inner pressure to do ‘something different’ rather than just throw a pre-built alert box, etc., then want to make sure the look and feel is consistent everywhere you throw an alert…

    What is more, good advice on some remedies. Although I have long been a strong proponent of using ‘experiements’ in debugging, of course, I hadn’t really thought of asking myself if I was eliminating at least have of the problem each time…said roughly.

    I would add one more psychological effect: Stuck in the end game. There comes that point when you really can see the end of the spec’d project, but you have gained so much ‘ownership momentum’ that you start delaying that final ‘tada’ until everything is ‘more-than-perfect’. You can’t see clear to fix one small thing because your mind keeps wandering over all of the what-if’s like ‘well, first, what if the client passes an array…’. If you just, as you recommend, step back and ask what’s the spec, then you can get it fixed and out the door. One suggestion might be to start thinking about that golden period you mention of object factoring, etc., for the next project, so you’re parental impulses let you move on.

    Reply
  6. Olli
    Posted January 2, 2012 at 10:45 am | Permalink

    I often had to smile and thought “Yes sounds very similar” … Thank you for this very helpful articles. :)

    Reply

One Trackback

  1. By Talk 147: Tangaraptoren | RadioTux GNU/Linux on November 11, 2011 at 4:22 am

    [...] programmer’s greatest enemy, Four kinds of stuck, Keep taking steps forward [...]

Post a Comment Cancel reply

Your email is never published nor shared. Required fields are marked *

*
*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Holy Ghost Stories
Punch vol. 1
by
Jeff Wofford
  • Recent Posts

    • Finding C. S. Lewis’s Essays
    • What is Ethics?
    • SimCity to License Blizzard’s LocalServer™ Technology
    • When Game Development Stinks
    • An Invitation Back to Faith
    • The Four Moral Cultures
    • In Praise of Modern Board Games
    • Hitting a Dead End with FlasCC
    • My Top Ten Least Favorite Ethical Arguments
    • Suitors: A new, free card game for 2 to 4 players
    • The Sorry State of C++ Portability
    • The Sorry State of Game Portability
    • Come Play House of Shadows!
    • Elvis in Wonderland: An Example Game Pitch Document
    • I Cannot Read on My iPad
    • The Final Solution to the Travelling Salesman Problem
    • Angry Birds “Cloned” Crush the Castle, and That’s Okay
    • How Diablo 3′s Networked Standalone Campaign Secures the Auction House
    • In Defense of Article Clones
    • Diablo 4 to Feature LocalServer™ Technology
  • Recent Comments

    • Jon on What Does the Bible Say about Divorce and Remarriage? (Part 1)
    • monica on What Does the Bible Say about Divorce and Remarriage? (Part 2)
    • Adam Hoskins on How to Get Your Game Idea Made into a Game
    • DevlinEdora on Why Won’t Developers Listen to Your Game Idea?
    • Kevin on How to Get Your Game Idea Made into a Game
  • Categories

    • blogging (3)
    • books (13)
    • culture (8)
    • employment (3)
    • ethics (6)
    • faith (35)
      • Bible (3)
    • family (7)
    • fiction (6)
    • games (51)
      • board games (2)
      • Crush the Castle (6)
      • House of Shadows (1)
    • iPhone (14)
    • language (1)
    • Mac (4)
    • music (4)
    • Phit (6)
    • politics (5)
    • productivity (8)
    • programming (35)
    • science (2)
    • technology (28)
    • thinking (13)
    • Uncategorized (7)
    • writing (15)
  • Archives

    • April 2013 (1)
    • March 2013 (3)
    • January 2013 (4)
    • December 2012 (1)
    • November 2012 (1)
    • October 2012 (3)
    • August 2012 (1)
    • July 2012 (1)
    • June 2012 (4)
    • May 2012 (3)
    • April 2012 (2)
    • March 2012 (3)
    • October 2011 (7)
    • September 2011 (3)
    • August 2011 (3)
    • July 2011 (2)
    • May 2011 (1)
    • January 2011 (2)
    • June 2010 (4)
    • May 2010 (2)
    • April 2010 (1)
    • February 2010 (1)
    • January 2010 (3)
    • December 2009 (8)
    • November 2009 (2)
    • October 2009 (2)
    • September 2009 (1)
    • June 2009 (10)
    • May 2009 (5)
    • January 2009 (1)
    • December 2008 (2)
    • November 2008 (3)
    • October 2008 (1)
    • September 2008 (2)
    • August 2008 (1)
    • July 2008 (1)
    • June 2008 (2)
    • May 2008 (8)
    • April 2008 (3)
    • November 2007 (1)
    • October 2007 (2)
    • August 2007 (5)
    • July 2007 (4)
    • June 2007 (8)
    • March 2007 (1)
    • November 2006 (3)
    • April 2006 (1)
    • March 2006 (1)
  • RSS Links

    • All posts
    • All comments
  • Meta

    • Log in
Copyright © 2013 Jeff Wofford. All rights reserved. Powered by WordPress. Built on the Thematic Theme Framework.