To my future self ten years from now: this post is for you.
Late last year I shipped the biggest update to my flagship app in its thirteen year history. If you’re not familiar with the app or my tiny software company, don’t worry about it. Those details aren’t important.
In my announcement to my customer mailing list, I promised that more important than the immediately available updates, was that this release laid the groundwork for many more significant future improvements and new features. I even went so far as to make the biggest mistake a developer can make: I promised a ship date for the next round of improvements.
The reason I put that date out there was because I felt guilty. Despite this release being the culmination of nearly a year’s worth of work – and an insane seventy-one hours spent coding during the final four days leading up to the Black Friday launch, I still felt like it wasn’t enough.
So I basically said “Upgrade today, and I’ll deliver even more in forty-five days”.
That deadline came and went in mid-January. Sure, I’ve shipped eight app updates since then, but they’ve all been minor releases. Bug fixes and some nice improvements, plus a bit of polish. But certainly not what I was aiming for.
I’m happy to say, though, that now I’m finally in the home stretch of delivering that first big round of improvements that all of 2019’s foundational changes made possible. It’s not complete yet, but I can see the end goal.
But that’s not the point.
Getting to the Point
The above 250 words were just to provide context for the rest of this post.
Since August 27, 2007, my little app has seen
- 142 releases
- 2,200 commits (that I’m aware of)
and the currently shipping version has 54,501 lines of code (according to SLOCCount).
I’m also quite proud of this milestone from last year:
And I also managed to ship the worst bug of my career recently, too.
And despite all that work, all of those updates, and all of the bug fixes and new features they contained across thirteen years, there is a single, twelve year-old ticket that I’ve never closed.
Call it a bug. Call it a new feature or an improvement. Whatever. But it relates to a critical piece of my app’s infrastructure that literally allows the app to do its job. (I’m purposely being vague about the technical details because I don’t want them to be the focus of this post.)
My current way of making things work is an incredible hack that relies on a system framework deprecated in OS X 10.8. Over the years, I’ve migrated to slightly different (but not really better) approaches, but they’ve all been stopgaps, half-measures, and so very clearly the wrong way of doing things.
And it’s remained that way because I’ve been afraid.
Obviously the focus of my career has been building for Apple’s platforms, but I’ve worked with so many different tech stacks, languages and frameworks over that time. And for the most part, I’ve been fortunate enough to get up to speed quickly and find success with each.
But always, always in the pit of my stomach, deep down in the back of my lizard brain, there’s this nagging voice when it comes to the low-level work, the real work, the type of code that real developers write
You’re not good enough. You can’t make it work. You’re not smart enough to figure it out.
So I keep punting on the work. I keep pushing that bug fix further and further out and just hope that my code keeps working and that a random macOS point release doesn’t bring it all crashing down.
I’ve made a few false starts at writing the code the correct way. I first learned Objective-C and the Cocoa frameworks from the Hillegass book seventeen years ago.
And then shortly after moving to Cupertino in 2007, I vividly remember browsing the computer books section in the Barnes & Noble on Stevens Creek Blvd and finding this:
I bought it, and took it back to the economy, extended-stay hotel I was living in and spent the evening browsing through every topic.
I don’t know why I was so in awe of the book. It may have simply been that it was titled Advanced Mac OS X Programming. Or maybe just that so much of what it covered was so far above my head at the time.
But then, right there in the middle of that book, was a section on the right way to approach the problem I’m still struggling with in my app today. (Well, what was the right way back then. Things have changed, but the new APIs are in a similar ballpark.)
So it hasn’t been that I’ve been unaware of what to do for the past decade and a half. I’ve mostly known how to go about solving the issue. And as I’ve dug into the sample code I’ve been able to find online over the years, I’ve built a mental model of how all the pieces fit together, but the technical underpinnings still elude me.
And I guess that’s OK. That’s the point of system frameworks and APIs, right? To an extent, they’re made available to paper over the low level details and give developers an easier interface to work with.
But there’s just something about this particular stack and area of the system that has become a permanent roadblock in my head. It’s so far outside of my expertise that my normal willingness to dive in and learn something new takes a back seat and is blocked by fear, worry, guilt, shame, and so many other awful unnamed emotions that whenever I even think about attempting to work on this feature my self-confidence vanishes, I shut down, and turn to adjusting font sizes and margins to distract myself into feeling better.
For me at least, it’s my ultimate expression of imposter syndrome.
And goddamn it sucks.
Light
But.
I have a deadline.
Not just a self-imposed release date, but an actual contractual obligation to get all the work I’ve been focused on since the last big release in November done, tested, and shipped next month.
The third week of May is going to be a huge opportunity to reach a new market and acquire new customers. And I want to put my best foot forward. The app is feature complete as far as the new stuff I want to ship. My focus now and over the next seven to ten days is smoothing out the workflow of the app and just making it better and easier – especially for new customers. It needs to Just Work.
And so two nights ago I sat down in my office. And just fucking did it. I told myself “no” was not an acceptable answer and dove into every arcane, unmaintained bit of Apple documentation I could find. Searched old Cocoa mailing lists for sample code, and finally, finally have a working solution.
For forty-eight hours, I was knee-deep in UNIX sockets and C code, exercising programming muscles that I haven’t flexed since I was an undergrad almost twenty years ago.
What I’ve built is nothing novel. It’s exactly the same solution that every other system-level Mac app or utility is using.
The difference though, is that after thirteen years I finally got past my own shit and mental demons and made it happen. I guess I was just fed up with myself constantly ducking out of doing the hard work. That, plus a looming deadline I have to meet, finally held my feet to the fire on this particular feature in a way that has never been done before.
I reached the light at the end of this particular tunnel. So many features. So many bug fixes. Thousands of customer emails and replies. Brainstorming sessions. UI mockups on the back of napkins at bars or doodling on a notepad while at my real job. But this one damn bug was always out of reach. And now it’s done.
So, to my future self ten years from now and anyone else reading this post, I’ll leave you with this picture.
I don’t know where that picture came from or who originally made it. My former therapist gave it to me six years ago. I printed it out, and it’s been hanging on the wall above my desk ever since. I need to remember to look at it more often.