I was to take six weeks off until a minor but very painful condition afflicted the plan’s back end: instead of returning from a fitness retreat, I’m recovering from (very minor and extremely helpful) surgery. It was convenient, as events were unfolding, that those last three weeks had already been fully allocated to improving my health. And this was an ideal wake-up call — impactful, constraining, ultimately easily fixed and nothing serious — for a fellow approaching yet another birthday since the last time he was in playing shape. Next week at this time, thanks to the flexibility and support of my employer, I’ll be at that fitness retreat after all.
This week I’m taking a brief meta-sabbatical from taking time off, doing some fun company-internal stuff I don’t usually get to spend my workdays doing. And I’m doing half of it from home, which affords such activities as sitting outside with the dog and writing, and which constitutes both a change of pace from last year and a setting of the pace for when I rejoin my current client (in a new role) at the end of February.
Modulo CodeMash and this week of doesn’t-really-feel-like-work, I’ll have been away for two and a half months. I seem to have backed into hibernating for the winter, which is a neat trick, though I’m not at all eager to repeat the experience. What I’m plenty eager about is expecting to be returning in my best health in years.
Here’s a bit of what I got done during my time off:
- Created an RSS feed for my upcoming speaking engagements, including the inaugural Agile Alliance Technical Conference
- Posted missing materials from many past talks
- Spoke at CodeMash: one regular talk and one lightning talk
- Recorded an episode-to-be of Geek Joy
- Recorded an episode-to-be of Agile for Humans
- Still expecting to see a couple short, stylish YouTube videos at Crash Course Crayon soon
I’ll tell you the rest when I get back.
Schmonzcast #20: It was during last year’s Agile and Beyond lightning talks that I introduced my new micropodcast. The night before, to have something to announce, I’d written, recorded, and published two episodes: one to frame my aims, one to start fulfilling them. I hoped folks would go find them, listen, and be interested to hear what might come next. During the CodeMash lightning talks a couple weeks ago, I tried a more direct approach: given the 5-minute timebox, if I moved fast, I could get through both of those introductory episodes. Here they are, in the first ever live performance of Agile in 3 Minutes.
- Video (excerpted from the original, by ZAGGStudios, of all the lightning talks)
Schmonzcast #19: Three years ago, I attended my first big tech conference. At CodeMash 2013, the contrast with my workplace made apparent just how isolated I’d been from modern software practice and its practitioners. I was reminded that other kinds of workplaces exist. And I found myself, revealingly, a bit embarrassed to tell people where I worked. CodeMash was a catalyst for changing my job and reshaping my career. Now I’m a software development coach with Pillar because I want to help folks who are trying to do good work and finding it painful, a struggle I know well. In this talk from my fourth CodeMash — and first as a speaker! — I share some stories of that struggle.
(I gave a shorter version of this talk at Agile Roots.)
The talk was based on this series of articles:
Last year at this time, I was nearing the long-awaited end of a longer-than-needed sabbatical during which I was angling to get hired as a coach. It worked out. I’ve just finished up with my first client team. I’m already feeling joyous pangs of anticipation about what might come next. I should keep doing this.
But not yet. Traveling every week for a year has worn me down. When I’ve been less effective at caring for myself, I’m less effective at caring for others. I’m not ready to offer myself in the way that coaching requires.
Stop and recharge
Feeling that I ought to keep doing this, but also feeling that I can’t keep doing this, I did some self-retrospecting. My first “try this” is to address my immediate need to look after my own needs. So I’m taking six weeks off, starting now:
- Two in Germany to be with my in-laws-to-be for the holidays (as usual)
- One in Ohio to be at CodeMash (as usual)
- Three in Indiana at a fitness retreat (very much not as usual)
As may be evident, the themes here are to renew and reinvest in my connections to loved ones, to programming, and to my physical health.
I’d hoped to build up a buffer of podcast episodes so the show would continue uninterrupted in my absence. That didn’t happen. When I recently missed a week, that was a gift: it helped me let go of the idea that I must keep going no matter what. When I was about to take some vacation in July, I highly doubted my self-discipline, and the show was just taking flight; in my mind it still is, but as of today it’s averaging over 300 downloads per episode, for a total of more than 10,000. These days, I’m much more willing to believe that I’ll start a new streak when I get back, and that you might still be willing to pay attention when I do. So my time off will also be a break from podcasting, from writing on this blog, and if I’m smart, from consuming Twitter maniacally.
Then go slower
My second self-retrospective “try this” is to address my need for a pace I can better sustain. So my next assignment will need to accommodate at least one travel-free week per month. That will give me much more time with my favorite person and furballs, much more rest, and the chance to participate in the thriving tech and Agile meetups in my own neck of the woods.
I’m not sure yet what I’ll be doing when I get back to work in February — perhaps at the same client, perhaps elsewhere. Whatever that challenge is, I’ll be physically and mentally ready. It had better be ready for me.
Keep in touch
I’ll be significantly less on the grid, but I won’t be off it. I’ll be happy to hear from you about anything that’s on your mind. Meanwhile, if you’d like to read more from me over the next month and a half:
- Browse this blog’s articles by tag
- Read the “TDD in Context” series in the sidebar
- Read other of my best-liked posts, also in the sidebar
- Buy the Agile in 3 Minutes book
To hear and see more:
- Come to my CodeMash talk
- Look for my first “Crash Course Crayon” video to drop in a couple weeks on Pillar’s YouTube channel (RSS)
- Catch up on my seven guest appearances on Ryan Ripley’s Agile for Humans podcast (RSS)
It’s been a fantastic and formative year. For your attention and encouragement, I thank you, and I hope to live up to it in 2016.
Expertise is learning
This recent tweet resonated with people:
An expert is someone who keeps learning even when learning is harder to find.
I’m hesitant to claim expertise about much of anything — not least because being an expert doesn’t imply continuing to be an expert — but I’ll readily admit to being pretty good, when faced with a problem, at learning whatever I need to learn to solve it. If I’m expert at anything, it’s that.
Debugging is learning
This less recent tweet of similar form resonated with considerably fewer people:
A bug is a mental-model mismatch. Your mental model of the code is a cache. To debug well, clear your cache.
A bug is when we thought we knew something and it turns out we don’t. So debugging, by definition, is learning: figuring out what we don’t know, then problem-solving our way to knowing it.
I can’t stand debugging
I like things I’m good at. I’m good at learning. I hate debugging. Let’s debug that.
If we need an extended debugging session, we’ve screwed up. We’ve arranged to have no idea how close we are until we’re suddenly done — if we’re ever done. We’ve arranged to spend an indeterminate, unbounded amount of time and patience to learn something very crucial and small, late in the game, when it’s expensive.
Had we arranged to spend a tiny bit more time and patience earlier, we could have been directing our efforts much more productively (and predictably) now. But here we are, debugging. If I can’t get over my revulsion at having put ourselves in this situation, I compound the cost. So I’ve learned to get over it and on with it.
I’m okay at debugging
I have no particular skill with debugging tools. I do have particular skill at developing software in a way that minimizes the need for debugging. Sometimes my ego-wires get crossed and I’ll take pride directly in my lack of skill with debuggers. Whoops!
Even though I can’t stand debugging, it is learning and for that reason I am (if I can get out of my own emotional way) somewhat skilled at it.
Debugging even when debugging is harder to do
When my niece is ideating, she says “How about this?” Sometimes more than once, to buy time, and perhaps also to generously prepare me to board her flight of fancy.
How about this? There’s a bug. If we don’t fix it, a whole bunch of related functionality that is very valuable (and urgently needed) is fairly useless. So we need to fix it.
We didn’t write any of this code. We have only a surface familiarity with the problem domain and the system architecture. We are, nonetheless, going to be the ones working on this bug.
The bug is somewhere in a big pile of long-method, interspersed-concern, tightly-coupled, ServiceLocator-using, completely-untouched-by-test code. (But I repeat myself.) Naturally, we didn’t uncover it until pre-production. We can reproduce it fairly reliably there, given sufficient load and concurrency. We haven’t been able to reproduce it in any other environments. We aren’t allowed to attach a remote debugger in pre-production (not that that’d help me, because I’m awesome at not knowing debugger (whoops again!)).
What can’t we do?
This less unrecent tweet resonated with less fewer folks:
Chasing a bug, how often do you ask “Did that fix it?” Be kind to yourself. Get answers fast. Write a failing test first.
—Moi-même encore une fois
Do we know exactly where the bug is? No.
Can we reproduce the bug faster? Not that we know of. It would be ideal if we could first reproduce it locally in any way whatsoever, and then automate that with a failing test. We’d give ourselves many more chances per day to take actions that close in on the problem. But let’s say we know enough about the components in interaction to know it’s prohibitively expensive to try.
What can we do?
We can obtain server logs, and we see exceptions thrown from our code.
The feedback loop
Armed with the logs and the following technique, we can narrow down where the bug must be hiding.
- In the logs, skip past the app server crud to the stack trace from our code.
- In the code, inspect the method that threw the exception.
- In tests, identify all the ways that method can possibly throw that exception. Use any means necessary to get under test.
- For each place the exception could be thrown, add a guard clause that returns a sensible value right after it writes uniquely and identifiably to the server log.
- Deploy; reproduce the bug; collect the logs; verify that the new exception is coming from one level down the call stack; goto 2.
This is legacy code. We’ll increase visibility to make clunky private methods testable. We’ll mock anything and everything that should have been a fakeable dependency. The tests will be inelegant, but we’ll have some. The code is already inelegant, untested, and buggy. We’re making it slightly more inelegant, but so what? We’re going to make it less buggy where it really counts, and we’re going to leave behind tests covering code that was evidently both valuable and hard to get right.
When we detected the system’s fingers tingling, that was just a symptom. The technique here is to squeeze the capillaries and push toward the heart of the bug. N times through the feedback loop, as we’re putting tests around the Nth method down the stack, we’ll realize we’ve arrived. This must be the place. Then we can write a test that’s red because the bug exists, and turns green when we’ve squashed it. When we redeploy and can no longer reproduce the problem, it’s gone.
Despite all the obstacles, we figured out how to learn what we needed to learn to solve the problem.
This method might seem like brute force. In a way, it is. If we’d been test-driving all along, the effort would have been amortized, and it wouldn’t have occurred to anyone that concerted effort was required to avoid this bug. It probably wouldn’t have occurred to anyone that this bug could even exist; after all, it didn’t occur to us this time.
If we needed brute force, it’s because we made ourselves need it. We are not obligated to continue doing this to ourselves.