Photo by Nandhini Kumar on Unsplash
As developers, we're presented with the vastness that is software engineering. This, along with the rate of change in the field, causes us to skip over crucial knowledge that is essential to our careers. Rather than backtracking and working on these obvious knowledge gaps, we tend to jump to the next hot tech. It may not be today, but one day you're going to wake up and realize you should've listened to your mom and eaten more broccoli.
Every single engineer has an area in their skillset where they don't feel confident. For you, this could be dynamic programming (bean sprouts), or greedy algorithms (cabbage), or even assembly (eggplants). For me, recursion is my broccoli. I don't know why or how it got this way, but ever since the start of my programming career, I've always hated recursion. I just couldn't wrap my head around it! And anytime I had to use it in a codebase, I would procrastinate until the last moment where I would rush to make something work – usually all thanks to Stack Overflow.
My aversion to recursion got so bad that I would feel physically anxious anytime I knew I had to implement a recursive solution! After years of escaping my broccoli, I was put on a project at work where I couldn't run from it anymore. I had this giant unknown data structure, which could have infinite levels of nesting, and multiple permutations of what could exist at said levels. I needed to walk over this data and allow changes to be made in a predictable, replay-able manner, all without losing the context of where I was.
My first implementation of this 'walker' was pretty haphazardly put together. I brought in an external tool to do the walking for me, as I hoped for the best and put band-aids on bugs that were introduced from this abstraction. Somehow though, I was able to ship a half working piece of code that got my team across the deadline.
But I wasn't happy. I knew deep down that my code wasn't stable. I knew that I had taken an easy shortcut that would bite me in the butt later. And that's exactly what happened.
Fast forward a few weeks and the walker had been tested against real usage. The number of bugs that were filed was growing more and more, and I was starting to feel less and less. It finally got to the point where I decided I had to rewrite this. Only this time, I would at least try to do it right.
I still used the external tool as a starting point, only this time I dove into the source and tried to understand how it actually worked. I then pulled out a pen and piece of paper and wrote out exactly what I wanted to achieve at each new level. This got me to replay how the walker would work with real data – something I knew worked very well for me in the past. After finally understanding exactly what I wanted at each step, I started implementing my algorithm.
After a few days of struggling through possible edge cases and permutations, I was able to ship my new recursive walker! This time I knew exactly what was going on, which made dealing with more edge cases and mutation related bugs much easier to squash.
We realized mutating the original data introduced far more bugs and was less maintainable than only tracking changes to the data. This was another opportunity for me to try my broccoli, only this time I was much less nervous. I'm proud to say that I was able to rewrite the walker in a much 'smarter' way in under a third of the time it took me the previous iteration!
It's okay to not know everything. I'm definitely not a broccoli lover yet, but at least now I know that I can tolerate it. But I do know that after each new broccoli dish I try, I'll get one step closer.
P.S. I'm actually a huge foodie and love all veggies. Sorry broccoli. 🥦
One of the most consolidated misconceptions about programming, since the early days, is the idea that such activity is purely technical, completely exact in nature, like Math and Physics. Computation is exact, but programming is not.