In 2012 I started “taking seriously” making coffee. By that, I mean that I spent a considerable amount of money, time, and effort, learning to brew espresso at home. Rather than bore you with the history, suffice it to say that this quickly became an expensive hobby. I wanted a challenge outside the realm of building software, and I’d found it.
My setup included a Baratza Virtuoso grinder, beans both from Kicking Horse and from Speakeasy Coffee, and the centerpiece, a Rancilio Silvia Pro V3 espresso machine. This machine has the reputation of being a teacher, and I can see why. I had at best a love/hate relationship with Silvia to that point.
Over the winter holidays 2011-2012, Sarah and I stayed with her parents, and so I bought Silvia and shipped it there with the goal of brewing better espresso during our month of down time. I knew I wanted to step up from the department-store brand espresso machine I’d used for a few years, and Silvia seemed a popular and strong choice. I unboxed the machine, pulled a few shots—that’s the lingo, you see—and did not care for the results. The espresso tasted considerably inferior to what I’d managed to brew using my $200 machine. This simply couldn’t happen, and so I did the simplest thing: I read a few dozen articles on the web about taming Silvia.
With Silvia, It’s Complicated
Talk about complicated! So many variables… beans, grind, tamp, humidity, water temperature, water quality… I didn’t know where to start, so I did the only thing I could: I muddled through until mid-January, boxed Silvia up, went back on tour, and waited until I could unite Silvia with the Virtuoso grinder at home. I couldn’t run a “real test”, after all, until I used the machine in a proper environment, with a high-quality grinder, high-quality beans, and even time and patience to experiment.
Fast forward to the July 2012. I had set up my beautiful grinder along side the temperamental Silvia. I fed this system the best water I have, the best beans I had, and I started pulling shots. Dreck. Bitter. I was pulling shots anywhere from 10 to 18 seconds. Water was channeling through the coffee at breakneck speed, spurting bitter fluid everywhere. Each shot created a unique, almost artistic mess to clean up. I literally couldn’t swallow the results. With Sarah waiting for her morning cappuccino, I resigned myself to take the best two out of 6-8 mediocre shots, and hope that cinnamon and microfoam milk mask the flavor enough. I didn’t feel good about the coffee I made, but Sarah went along with it kindly enough.
Wasn’t This Supposed To Be Fun?!
I wasn’t enjoying this. After reading a few dozen more articles, like this one, I saw that in order to get the results I expected, I needed to learn a lot more about making coffee than I already had done, and I thought I’d learned a lot already! I’d read The Joy of Coffee over ten years ago. I seemed to know more than most people around me about making good coffee. I owned an Aeropress! Surely, I knew what I was doing. Apparently not. It seemed that, no matter how much I thought I knew about brewing beautiful espresso, there remained entire worlds I hadn’t explored yet. I wanted to enjoy this, but it had become a battle, and I didn’t know whether I wanted to learn all this arcane technical stuff just to make good espresso. The results from my $200 machine seemed like an acceptable compromise by that point.
I know—so far, this has nothing to do with software development.
Gil Broza decided to have a little fun at my expense.
@jbrains not test-driving the coffee maker, eh?— Gil Broza (@gilbroza) July 1, 2012
Now, this has something to do with software development.
Legacy Code: If You Don’t Know Everything, Then You Don’t Know Anything
This entire experience reminded me of the battles we face working in legacy code. We don’t know precisely what the system does, though we have a rough working knowledge of how it works and what it’s supposed to do. We only have one form of reliable feedback: the end result. We might manage to check a few intermediate steps in the process—I can roughly check the temperature of the water, the color and shape of the flowing coffee, the time to pour 2.5 ounces of espresso, and how much splatters out from my naked portafilter—but that feedback is inexact, like how wet or dry the puck of grounds feels after pulling the shot, or how much crema I find on top of the espresso. These forms of feedback tell me when I’ve got it all wrong, but don’t help me know when I’ve got it somewhat right. It certainly doesn’t help me know when I’m getting a little better. I can pull a 23-second shot of 2.5 ounces with a nice dark color and a healthy crema on top, then taste unrepentant bitterness in the shot. Unusable—but everything looked right! What the hell am I doing wrong?!
I really had only two choices: give up, or learn more. In my case, giving up meant walking down to Samuel’s coffee house and paying $3-4 per cappuccino. This usually gives me the quality results I want, but at a premium, and comes with one considerable downside: I have to put on pants and go outside. When working with legacy code, giving up means neither replacing nor rescuing the legacy code, but simply living with it, learning to adjust my expectations to its quirky behavior, figuring out how to get it mostly out of my way, but with one considerable downside: when push comes to shove, I can’t change it, so I have to waste time and effort working around it, rather than making it better. Legacy code has a way of creating a vortex of mediocrity around it, sucking in otherwise good code and diligent programmers. We bear both visible and invisible costs, and they seem unbounded. It never ends, and we can do nothing to stop it.
A little dramatic, perhaps, but I think you’d agree, not entirely unrealistic.
For my part, I won’t give up the search for a great espresso. I won’t let Silvia beat me. I will do the research, put in the practice, and figure out how to get consistent, delicious results. I have done it before, and I will do it again. I will have to read a lot of articles, try a bunch of strange-sounding techniques, run through a lot of beans that deserve better treatment than I’m likely to give them, and drink an unfortunate number of mediocre cappuccinos before I get there, but I shall get there. It will happen, because I believe I can learn to do it, I believe I will to learn to do it, and dammit, I want great cappuccino at home.
It’s now late 2015. I have a new grinder, but the same old Silvia, and now pull better cappuccinos than I used to. All the same, I don’t really understand how it all works, I can’t really diagnose problems, when the humidity changes I have to adjust my grind, and if I don’t follow the same ritual very closely, then I don’t get the same results. It all feels quite fragile. I can live with it, because I get a lot of value from the cappuccinos, but it just doesn’t feel comfortable. So it goes with legacy code. I really wish I could refactor my espresso machine comfortably.
I could add a PID, which helps regulate water temperature, but I’m really afraid that installing one will cause me to destroy the machine, so I’ll wait until I can justify investing in a new one. I’ll add a PID, I’ll be able to better regular water temperature, and everything will be better? (Sound familiar? We’ll hire a new CTO, throw it all away, do it in Python, and we won’t make the same mistakes this time. Sure.)
Epilogue To The Epilogue
It’s now almost the end of 2018. I have the same grinder—well, a new instance of the same kind of grinder—and the same Silvia. Although showing some signs of rust, the machine continues to work. I pull good shots most days. I don’t have to work quite as hard as I used to for the results I get, but I also know that better results are possible. I occasionally watch videos to try to improve, but it amounts to an absurd amount of trial and error. I haven’t installed a PID yet, mostly because it looks more complicated and expensive and risky than just trying some new technique from some self-styled barista with a YouTube channel. Most importantly, I still mostly don’t know what I’m doing. That’s legacy code: you can get used to it, but it never quite feels right.