One day during a review of some changes, a new user interaction was introduced that was basically making use of a toggle in the place of a checkbox. This gave rise to the desire to make other parts of the system have one user control for this behavior. It was said that the change in one spot to use a toggle, with other spots still using the old antiquated checkbox, would confuse users. We should instead take time to understand how far the change would need to extend.
Fast forward a couple of months, one early morning I suggested to a colleague that we create an email group for our team. He said "yeah, but then you have to keep up with it when people come and go, and it becomes a big pain and get's out of date and kind of a hassle" to which I replied something to the effect of "welcome to my world and what it's like to maintain software".
A parallel to both of these is when we collectively as a team say, "Yeah, let's go with the hack for now so we can release...and then later we'll come back and clean it up." What's the commonality? Where is the parallel? All three are a point in time where a decision has to be made about maintenance in one form or another.
What does a hack look like? It comes in many forms. Oddly placed "if(...)" checks sprinkled around. Ever growing indentation levels in a method, indicating harder and harder to understand logic to get you down into those inner most levels. Duplicated identical switch statements hiding classes that are waiting to be born. Code smells sprinkled here and there, and... and... and everywhere.
This business decision of a "short term hack" leaves a bunch of garbage laying around in the code. As a team, we may have great intentions of "coming back to clean it up". But the reality is, that rarely happens... and when it does, it can be the exceptional case. Look, I get it. There is often not any perceived value of coming back to take care of it. But I as a user of that code, have to deal with that. And so do the poor schlubs that I work with that bump into that hack and are left scratching their heads.
It's confusing on several orders of magnitude larger than someone having to handle grocking a checkbox vs. a toggle, or to maintain an email list. Over time, more and more of these "compromises" cause the code to become more and more brittle. It becomes harder and harder to change. Harder and harder to understand. To reason about. The compromise is on the side of the code. The health of the artifact that should be an enabler of speed... of our ability to pivot late in the release cycle... rather than a drag on our speed, becomes more and more un-healthy.
When things begin to take longer and longer to deliver, do we ever look at one another as a team and say "well, this is because we have made some "compromising" decisions along the way that have affected the code adversely and now we're feeling it". I think that's often not the case. Sometimes it is, don't get me wrong. Sometimes we do recall those compromises. And sometimes we take the time to inject some health back into our code artifact.
But, more often is the case that we have lost all context from those far off historical decisions, and now we just feel the pain. Whether it be from too much time passing, or because people that came to the initial "compromise for a short term hack" are no longer around working on the code / on the project / with the company. Or maybe they are still around, but they are not the one staring that compromise in the face at the moment, you are...you're the poor schlub I mentioned above. And there is no way for you to recapture that intimate moment of the past where yes we were able to deliver back then... but now... now you have a story on your Kanban board that's taking forever to make it out of the "Developing" column. So the "compromise" has come back and is staring the larger company straight in the face, specifically you... your product owner... your team. And there you stand as a developer with a cracked egg all over your face. Given enough complaining room and frustration and you might just start to sound like a crotchety wind bag full of hot air about how difficult the code base is. Product owners don't care to hear about the difficulties of the code... they would much rather hear that your story is complete and your ready to take on more work.
Being honest about what it takes to keep a code base healthy is not an easy thing. It's soo necessary though. Be a professional. Do the right thing by the code, and keep lines of communication open between you and your team about what your doing and how it's coming. No, you can't fix the whole system in the course of one story. But yes, you can chew on a mouthful of it. Always making small improvements, and biting off some larger ones along the way can breath new life back into the code asset as well as your team.
Fight like hell to keep them out. Don't offer them up as an option. But (and I do mean but), if you do have add in a "short term hack" in order to deliver (let's all be honest here... it happens... delivery has to happen, it's what keeps the lights on), insist at the very least that a story is created to come back and address the hack. Leave some artifact as a conversation piece to come back to. And make sure that story has plenty of detail around it, capturing as much of the moment as possible to get you back into the context of when the "compromise for the hack" was made. And then fight like hell to play that story as soon as possible.
Short term hacks become long term hacks that harm code agility. Even more, they become longer term problems as you design more and more of your system around them... making additional compromises... predicated on the far off and often forgotten past compromises that the company as a whole made. Keep the code agile, and your company will be too.