This was originally posted on my blog.
As a father of two, one of which being very recent, it's been tough to find time to blog as much as I usually do. It's tough to find/make the time without cutting corners somewhere. But it's interesting how the two: parenthood and development, might intersect a bit more in unusual ways than one might think.
This is the story of one such intersection that occurred a few nights back when I was reading a bed time story with my son entitled "Ice Cream Soup" by Ann Ingalls. Ice Cream Soup is a book about a young boy that wants to make an ice cream cake. He starts off simply enough, and continues to add toppings, until eventually he ends up with a total mess: ice cream soup.
It's a perfect analogy for the world of software. Anyone that has lived through the entire life cycle of a real-world project has seen it happens first hand.
Our story begins with a boy that wants to make an ice cream cake. So he grabs some toppings, a big blue pan, and some ice cream and dives on it. He has a vision and knows what he wants, so he just goes for it. It's too simple to mess up right?
We all want that latest greenfield project to be perfect, or as perfect as it can be. It's all new code, simple requirements. We can write unit tests, set up a beautiful build pipeline, follow the best standards, embrace the best technologies to their fullest potential.
Every pull request on the team is meticulously reviewed, ensuring all the patterns are followed, tests are written, and all that good stuff. With the initial release just around the corner, the entire team is feeling great... for now.
As our young boy continues constructing his delicious ice cream cake, his mind begins to wander. He notices all these toppings that wants to add, which weren’t at all part of his original plan, so he must adapt and shift things around to squeeze them in:
I pat it down.
I pat and pat.
Now I can add some of that.
Requirements always change, scope creeps, and that’s how it always goes. Our job as software engineers is being able to roll with these punches to ensure that our product provides the value and features that our customers expect. Our perfect greenfield project that was meticulously designed might not handle these changes well. There is rarely time for re-architecting, we must ship, and we have to make this work.
So, we “pat it down”, we sneak a feature in here that might not follow our best practices. We’ll throw some comments in there, maybe spin up a ticket to refactor it, but the hacky solution is in there for now.
Or it may not be a feature at all, it may just be some shiny sprinkles that you want add to your cake that might not mesh with everything else. Things like writing your own search engine, message bus, or rewriting your front end to some hipster one you read about on Hacker News, either way.
The point is: any of these changes to your project, without adequate planning or thought, can result in bad technical debt. As an engineer, you need to be okay with this because the survival of your business or product is often more important than what your code looks like.
The problem is that if you constantly are “patting it down” so you can “add some more of that” without taking the time to make sure your cake can handle it, it could start to fall apart.
At the end of our story, our young boy doesn’t have the beautiful cake that he dreamt of when he set out upon this journey, instead he has a big mess on his hands.
What did I make?
It looks like goop.
I think I made ice cream soup.
If you’ve been a developer for any reasonable period of time, you’ve been there; you’ve tasted ice cream soup. After multiple releases, last minute features, and deadlines all too often things get “patted down” to make room for “more of that”.
This cumulative result of these little sprinkles here and there can be a codebase that doesn’t look cohesive, copy-pasted code everywhere, and most often an environment that is ripe for regressions at the site of any major changes. You need to be okay with this. Software isn’t perfect, and much like baking, it takes time, practice, and experience to get things to work out as you planned (and even then, it still rarely does).
The point of all of this is that there are so many things outside of your control when developing software outside of actually writing code. At the end of the day, your customer isn’t going to care what things look like behind the scenes; they want to know if it does what it’s supposed to and “works”.
With that being said, there are a few things you can look out for to avoid your projects turning into ice cream soup:
- Iterate - If you have any type of leadership that is willing to listen, try and fight to have shorter release cycles. Even if they are just internal builds, this will help scopes from creeping out of bounds between releases, so you can manage any “organic” growth that comes up.
- Give a crap - This isn’t so much of an individual goal (although you should care), but more of a culture. Your team and managers should care about the product, both outside and in. Be mindful when pull requests come through to make sure that code isn’t being duplicated, or bad patterns aren’t being introduced. These are small steps, but they can make an impact.
- Stay the course - With technology moving as fast as it does, it can be tempting to try to jump on the latest framework or flavor of the month technology, but tread carefully. These types of decisions should be weighed very heavily to see if they are a fit for your project, your team, and what the goals of your product are long term.
As the story ends, our little protagonist has finished his cake and ended up with something completely different than he originally planned: ice cream soup. You might expect him to just throw it all away out of disappointment, but he doesn’t. He eats a huge spoonful, accompanied with a big smile and a “Yum!”.
Software rarely, if ever, ends up like it was planned and that's okay. Requirements change, scopes creep, and deadlines are real things that can quickly turn a beautiful recipe into software soup. Your project might look awful and it might be filled with horrible hacks that you pray never see the light of day. The beautiful thing about software is the end-user likely doesn’t know, or care, about your architecture, patterns, or hacky code. They want something that will make their lives easier, empower them, but most of: just something that works.
Much like the boy and his eventual bowl of ice cream soup, it came out looking like a mess, but was still delicious. Software systems are no different. I’m sure there are countless enterprises built on top of codebases held together by duct-tape, goto statements, and dreams. The key difference here, is that although they look terrible behind the scenes, they work, and they provide value.
Focus on controlling the things that you can when building your systems. Try to strike that beautiful balance of following best practices and being pragmatic (and document the heck out of things when you can't). Strive to inspire your colleagues to do the same and foster a culture of software craftsmanship.
So, after your next big release, don't focus on the negatives or how messy your codebase might be and instead focus on the value that you provided your customers. They don't know about all the different mismatched ingredients that went into your creation, or how you had to skimp and use the non-organic database or off-brand front-end framework. They do care that your software makes their lives easier and empowers them to do more.
That's the software equivalent of "Yum!'.