Time for me to pass on something I've been practicing for years but haven't found written down somewhere.
It's a simple thing. A practical thing. Forged in the trenches. It won't win any contests in which the audience gasps and says "oh, now that is clever." But it’s easy. Simple even. And it can save a lot of time and tears and, at the end of the day, isn't that some of the best stuff?
Here it is:
When debugging or testing your program, do not use data that looks like a variable or type name.
Do not use data that looks like a label or a column name or something your operating system has tons of.
Do not use data that looks like it’s part of the program.
Do not do this:
user = User::new(name: "user")
Do this instead:
user = User::new(name: "my-test-user")
Instead of this:
testpath = "folder/file"
Do this:
testpath = "my-folder/its-subfolder/moo-sounds.wav"
(If someone comes running now, fists clenched, eager to complain about the additional typing: I hope you slip on a banana peel.)
Never, ever do this, not in production code, but not even when testing and debugging:
return new Error("error")
Do this instead:
return new Error("uh-oh someone slipped on a banana peel")
Same goes for numbers. When you have to use a number somewhere, do not — never! even if you just slipped and fell and are hurting — use 1 or 0, like this:
sizeKilobytes = 1
Use a 9, or a 44, or go all in, baby:
sizeKilobytes = 999
user = User::new(id: 666)
Why?
What's code and what's data — user-input data, runtime-generated data — should be clear at first glance.
You’re testing, you’re debugging. The last thing you want is to be confused about what’s what when looking at logs, error messages, or a UI you’re trying out.
The first glance should tell you whether you’re looking at data you put in, or default values, or something else that floats around your system.
You do not want to waste time thinking:
“It says ‘username’ here. Wait, is that the label or the value? Is that the column name or the value of the username?”
When you see the error message “folder not found” you don’t want to ask yourself, whether that’s your test folder called ‘folder’ or some other folder.
Using data that looks like data, helps you avoid these:
“The log says ‘Creating entry failed: error’ — wait, is that our error we just put in or… any error?”
“It says ‘failed to create file’ — does that mean it failed to create another file or my file that I called ‘file’?”
"User 1 not found — is that mine or another one? How many do we create in this test?"
“Invalid size: 1 — wait, did that use the size I specified, or is that the default value?”
Maybe these examples sound contrived, maybe it sounds cute, but— look, just trust me on this one. This is not an artificial, feel-good tip. This tip is scar tissue turned into words. It has saved me hours. It stopped me from looking dumb quite a few times and, again, isn’t that what we all want?
Might not be number one, but certainly top five.
Great post, Thorsten! One of many places this pays off is E2E testing. A test will fail because there are two lines of "First name" copy on a login page– one is the form label, and the other is the mocked user's first name, which is "First name". Choosing data that looks like data avoids pointless failures like these.
Have you read the book on debugging by David Agans? He also mentions this quite a lot.
Also, in the last post you mentioned a podcast by Kent Beck as one of your top 5 podcast episodes of all time. What are your other top 4 episodes?