Motivation

A friend and associate, who recently started a potentially-commercial programming project of his own, asked me an interesting question the other day:

[…] Do you ever find you get discouraged when you try to code something and it doesn’t work, so you try a different way and it still doesn’t work? I’m finding I’m less and less eager to work on this because it’s been such a pain so far, but at the same time it’s a catch-22 because if I don’t work on it, then it’ll never get done. What kinds of things do you do to motivate yourself in times of low motivation?

Motivation can be a major problem, most especially to the self-employed (I speak from experience there). It’s also one that I rarely see addressed, so I decided to put my answer here. Be warned, it’s a little long-winded.

Let me reply with another question: how do you move a mountain?

A lack of motivation, for me, means that the thing that I want to do seems too difficult and intimidating, or seems like it would cost more (in terms of time, money, effort, or other resources) than I’m willing to spend on it. The answer to that is the same as the answer to the mountain question: you break it down into smaller pieces and move them one at a time.

Most of the time, when I don’t know how to get the computer to do something, I’ll at least know what I want a program to do — i.e. I’ll know how to do it by hand, and can work out the details by actually doing it and comparing my program’s output to what I came up with manually. In the few cases where that fails, I tend to get angry rather than discouraged (because, after all, it should work!), which drives me to find out exactly why it doesn’t work and fix it.

In the cases where I don’t (yet) know how to do something by hand (as is often the case with Project X)… well, that gets interesting. 🙂 One of the tricks that I’ve worked out is to list all the things that I need it to do and break them down as much as possible, either in my head or (preferably) on paper. That will often give me a map of what to do that’s almost directly code-able.

When I’ve got a part that isn’t, I’ll write about it in my journal, in terms as concrete as I can find. It’s hard to come up with solid examples for that, but I watch for any place that I use vague words or assumptions and try to make them concrete and spell out the reasons. For instance, “something” (what thing?), or “they” (who are they?), “I can’t do that” (what’s stopping you?), and the like.

Once I’ve spelled out the problem in concrete terms, I’ve got something I can go over and pick apart. “I can’t do X because I don’t know how to do Y or Z” — well, the obvious answer might be to learn Y and Z, so write those down as possibilities. Another answer might be to farm out X to a contractor, so write that down. A third might be to do X in such a way that neither Y nor Z are required, so write that down too. Don’t worry about the details yet, just try to come up with as many possible directions to solve each problem as you can.

When you’re done (and not before!), go through all of those possible directions and make a list of questions from them. You’re looking to find out whether each one is a feasible solution or not, so list the questions that you’d have to answer to find that out. How long would it take to learn Y and Z? How much would it cost to hire someone to do X? Is it even possible to do X without knowing how to do Y and Z, and how would I find out? By the time you’ve finished that, you’ve either found an answer, or you’ve got a to-do list of questions to research to come up with one.

Eventually, if what you want to do is possible, you’ll find a way to move forward with it. If it’s not possible, or would cost more than you’re willing to devote to it, you’ll at least know exactly why and how (which could suggest other things to do that are possible and cost-effective).

Test-Driven Development

In my recent side-project, Cpp-Markdown, I used a testing suite (developed by the author of another Markdown translator) as a guide to see what I needed to work on next, and to immediately show me when I broke something. It was a very nice way to write code… I could always see progress, and I always knew where bugs must be so I spent far less time in the debugger. Working from a testing suite and having a repository of all recent changes was like saving a game before doing something dangerous — I felt free to try anything, because if I totally screwed something up, I always knew about it within minutes, and could always easily go back to the last fully-working copy.

It was so nice, in fact, that I was reminded of a previous attempt I’d made at it, and I decided to further study the idea of Test-Driven Development (a.k.a. TDD). As luck would have it, I had also just started a new phase on Project X, one that TDD would be very useful on, so the decision to use TDD on it was a no-brainer.

The basic idea behind it is:

  • You start by writing a very simple test for whatever feature you want. Then you run that test, to prove that it will fail as it should. This is the red phase. Check it in.

  • Next you write the new feature code, just enough of it to pass the test, and run the test again. When the test passes, you’re finished with the green phase. Check it in again.

  • Finally, you go back and tidy up the code, eliminating any now-redundant parts and making it generally nicer. Run the full testing suite on it after each change, so you’ll know that no other bugs have slipped in, and check in the code every time the test suite says it’s okay. This is the refactor phase, which you might need to do several times to get the code to a satisfactory state.

  • Repeat the red, green, refactor cycle for the next thing you want to implement.

If you follow those steps and the The Three Rules of TDD, you apparently get near-magical results. From the “three rules” page…

[…] Indeed, I had been a programmer for nearly thirty years before I was introduced to TDD. I did not think anyone could teach me a low level programming practice that would make a difference. Thirty years is a lot of experience after all. But when I started to use TDD, I was dumbfounded at the effectiveness of the technique. I was also hooked. I can no longer concieve of typing in a big long batch of code hoping it works. I can no longer tolerate ripping a set of modules apart, hoping to reassemble them and get them all working by next Friday. Every decision I make while programming is driven by the basic need to be executing again a minute from now.

So over the past couple days, I redesigned the new part of Project X so that I could work on it using TDD. I have high hopes for it. We’ll see how it goes.