This syllogism drives my decision-making when I design and build tools

for myself. Let me walk through a concrete example, involving

automating some git tasks:

My Habits are Apparent in My Work

I’m working with a small team, detangling a highly

complected codebase.

Changing any feature means touching lots of different chunks of code.

In the course of such changes, we frequently encounter small,

logically unrelated problems — unrelated, but necessary to fix in

order to make headway.

Mostly those small changes get wrapped up in the larger feature. They

end up committed to the same branch, in the same pull request, and are

part of the same code review.

Code reviews get bloated, which means reviewers can spare less

attention.

The quality of our output is affected.

It seems to me that I need to change my habits in order to reduce the

size (and increase the coherence) of my commits and pull requests.

My Tools Determine My Habits

I have a friend who trains dogs. Some of the dogs she trains are

police dogs; the training needs to stick.

She said something funny to me: “We don’t use treats to reward our

dogs, and we never punish.”

That confused me. Reward and punishment — isn’t that how training

works? What’s left? She explained that they didn’t want the dogs to

respond to threats of punishment. They wanted them to respond to

correction. A correction is just a reminder of what the dog should

be paying attention to:

There’s this really interesting smell over there, I’m going to go

investigate, oh jeez, what a smel—

“Spot! No.”

— oh! Right! No time to smell that; I’m on the job!

Similarly, treats, she said, are a dangerous way to reward behavior.

Who needs a police dog that won’t do anything without a MilkBone

dangling nearby? Instead, dogs received social rewards from their

handlers: petting, happy voices, physical contact. This is a reward

that everyone wants the dog to want. No one’s worried about the dog

having too much.

She said they work hard to connect new habits to the habits the dog

already has, so that one triggers the next — that’s called

chaining.

When I’m writing tools for myself, I tend to think of myself as the

subject in an

operant conditioning

experiment — like a dog being trained. To change my behavior, I don’t

bribe myself with treats, or punish myself with cruelty — my tool is

what will train me, using corrections and “never too much” rewards.

In order to determine how the tool will work, I ask myself these 5

questions:

1. What behaviors do I want to exhibit?



I want to make lots of little pull requests; sometimes that means

making a pull request for a small fix even when I’m in the middle of

making other changes.

I want to make pull requests with well-defined scope.

2. What behaviors are undesirable?



I don’t want to make pull requests of indeterminate scope. I don’t

want to wrap conceptually disconnected changes, even if they’re

prerequisite to the main change.

3. How easy is it for me to do the right thing?



Right now? I have to create a branch, check it out, stage the changes,

commit them, change back, and then cherry pick that commit (or perform

some similar foolishness in order to get back those changes).

Once the tool is done? Once I’ve made and staged a few changes that I

realize shouldn’t be in this pull request, I want to be able to commit

them to a separate branch and pull-request them in a single command,

without losing them.

Anything more than a single command will involve too much cognitive

load — it will feel like a punishment.

4. How immediately rewarding is it to do the right thing? What’s the reward?



One of the reasons I love building my own tools is the inherent jolt

of pleasure I get every time I use them. The fraction-of-a-second

feeling of ha! It worked! is an incredible reinforcer.

(There is also the satisfaction of having more pull requests merged,

and having the review go more smoothly. Unfortunately, reinforcement

learning is very bad at connecting actions to distant rewards. If

the delay between is too great, it won’t reinforce good behavior.)

5. What will correct me when (or before) I start bad behavior?



I think it would be great if, when I branched, I was forced to explain

what the eventual pull request would contain.

Then, at each commit, I could receive a little reminder of what I

planned to do: a sort of alarm to check that all the changes fit the

description.

Remember, just like the dog, all I really need is an interruption to

stop the bad behavior. Once I’m thinking about it, I know the right

thing to do.

The Tools I Use…

The easiest way to create new habits is to tie them to old ones.

When I’m about to start on a new feature, I branch the repo. That

habit is in place.

When I’m about to start a new feature, I want to establish a tight

scope for the eventual pull request.

Put that way, the necessary change seems obvious:

Once the scope has been established, any changes that are necessary

but outside that scope should be made in micro-requests:

(Note that the changes are still on this branch, too — I made them

because I needed them! Now they can be reviewed on their own. Note

also that in my personal version of this script I’ve added a git

push too.)

With that, I’ve taken care of making the desired behavior easy — now

I need to add a correction to prevent bad behavior. When I commit to

the current branch, I should be faced with a reminder of the scope I

defined for myself. I’ll prepend it to the commit message template:

Now that the scripts are in place, I still need a few git alias ‘s to

plug all those parts together, and a few tweaks to my editor’s git

plugin (I use magit) and I’m done!

…Affect My Work

By thinking of my tools as dog-trainers, and myself as the dog, I’ve

transformed my git usage.

Before I started, I was faced with two onerous tasks: first judging

whether each change I make fits in with my original intentions, and

second (if they don’t fit) making a tiny-but-separate pull request by

stashing, branching, staging, committing, checking out, and

unstashing.

These were tasks I did rarely and poorly. That’s important: I didn’t

automate something I did all the time; I automated something I felt I

should do more often.

I built a tool that not only made those tasks easier, it connected

them to habits I already had: branching and committing. It rewards me

for doing right, and corrects me before I do wrong. I say why I’m

branching when I branch; I get to refresh my memory of that intention

when I commit; and if something doesn’t fit in, I can commit it to

another branch in one command.