Hacker News new | past | comments | ask | show | jobs | submit login

This suggests a "just in time" approach to cleaning up tech debt. Clean it up just before you write code which would otherwise depend on the debt.



I recently needed to make a change in how something common is done across several services. I made the change in one place (and have some passing unit tests), but then I realized that I’d have to duplicate more code than I’d like. So I’ll take a couple days to pull all related functionality out into a shared library.

This refactoring could’ve been done ages ago — there’s already some messy and duplicate code there — but now’s the perfect time to do it because 1) I’m already touching and destabilizing that area of the product, and 2) the clearer, de-duplicated code will be easier to spot check.


Makes sense. I guess for any given refactoring, the advantage of doing it sooner is that you get residual recurring benefits sooner. And the advantage of doing it later is you have more information about the requirements of your application and the "correct" way to do the refactor (or even if that code is going to be a long-lasting part of the app, cc Lindy effect). So whenever you touch any given piece of code which could use a refactor, you could try to figure out which advantage is more important right now.

Of course, if the total effort of doing the refactor plus building the feature on top of the refactor is less than building the feature on top of the debt, you should always do the refactor first. That's pretty much a no-brainer.

Another idea I've thought about is informally keeping track of possible refactors, maybe give them an informal prioritization, and taking a glance at your list before each task. Maybe there's some value in letting a refactor stew in your brain a little bit before actually putting it in to action. And continually maintaining a rough refactoring plan could help prevent your codebase from entering a state where it's actually unrecoverable.


Interesting, I think this is part of what the article is alluding to: what happens with tech debt is more to do with the team’s process rather than with the tech debt itself. Some teams are stuck in a process that makes them unable to tackle the problems even if they want to due to that process.

Of course you could just say “change the process” but it’s also obvious that there are many other factors and pressures that are non trivial


Also, as you alluded to, if you're changing related code which will require manual testing, then that decreases testing costs, if they're shared across the refactor and the new code.


Yeah I’ve got about five ideas for refactors that will make my life noticeably better. I’ve been pondering some of them for more than a year, slowly improving the design, but I’m still waiting for the right time when the ROI is higher.


Please no!

This isn't refactoring - it's just hygienic coding.

"Refactoring as you go" sets up an adversarial relationship between dealing with tech debt and the feature work that that the time and effort was actually assigned to. IMHE, human nature and engineering politics then means that tech debt doesn't get addressed at all until it's already too late.

Approaching with this intention also takes refactoring entirely off the roadmap - from the eyes of product management, refactoring becomes invisible and "free", and no longer requires budgeting for. "Why do you need time to handle tech debt? I thought we were refactoring as we go?"

By all means, it's good practice to leave the code better than you find it, but don't just leave the tech debt that isn't trivial, is too large to address immediately, to fester.

Instead, take notice of inefficiencies and cruft while working, and write tickets for it, so it can be seen and brought up for discussion, prioritized against other tasks. Perhaps even leave a comment on the ticket whenever you run up against the same issue, so there's a paper trail of the how serious the issue.

This way, at least management has visibility into the state of the codebase and can't act surprised when tech debt brings productivity to a grinding halt.

A lesser issue, but still important IMHE, is that actually trying to "refactor as you go" makes PRs inscrutable. What's refactoring? What's feature work? A little bit of noise here and there is unavoidable, but any refactoring substantial enough to increase development velocity is likely to make meaningful code review very difficult.


Agreed about mixing a refactor with the incremental feature add makes PRs confusing.

"and write tickets for it, so it can be seen and brought up for discussion, prioritized against other tasks"

I have been doing this for almost a decade now and I have at no point ever seen even a top-ticket tech debt item get prioritized. Ever. It's always too much effort for little payoff (in the eyes of the business).

I explicitly tell juniors that when I cut this kind of ticket, I do it because it is right, not because I think it will ever get worked unless I myself (or someone similarly insane) directly disobey marching orders to work on it.

And even when someone does disobey orders and refactor, it's often a pet peeve that isn't one of the more major ones. So that's fine but nobody ever one-man-armies against the real problems.

And to illustrate what I mean by "the real problems", let me explain. I like to talk about tech debt as high interest or low interest.

Low interest tech debt is the shitty python script I wrote the other day that took 1-2 hours of manual monkey work we'd have to do in Presto sql and that only 1-2 people even knew how to do, and makes it so literally anyone at the company can do it perfectly right in a minute or two. It's a shitty script, but it knows it's shitty, and tries to have no pretenses about it and make it as simple as possible to debug and make incremental changes to it. So yes, if I spent more than an hour or two on it, I would not have done it like this at all. And yea it'll probably be a little annoying to change the next time someone has to do it. But it saves a lot of time, didn't cost much, and it's not going to change how we design the system at all.

That last bit hints at what I mean by "high internet tech debt". High interest tech debt is how it takes 8 hours of babysitting to deploy a schema change. It causes blip outages in every region as you deploy it. It's so painful it perverts our schema design to minimize how often we have to migrate the database. And it's all because, shortly after the Big Bang, right in between photons existing and the first hydrogen nucleus existing, someone had a cool idea for a simple trick about how they could eat their cake and have it too with how our databases work. And we have paid for it ever since. And they built on top of the primitives this offers so deeply that we'd have to change a ton of shit to make it work. The best time to fix this was 5 years ago, the second best time is now, and I guarantee you we will never ever do it. We'll replace the whole thing with something else because it's shiny and will be worse for years before we actually just pay down this tech debt


I'm looking for a job where this is feasible. And I'm not even being sarcastic, I'd take a pay cut for such a workflow.


Seems like maybe shops have a tendency to get stuck in one extreme or another, either shoving crap out the door or else excessive concern with prettifying minutia.


I’ve literally never seen the latter: I think companies that do that just disappear. The former though is a great driver: Let your debt pile up sky high because it doesn’t matter as long as it lets you make more money in short term vs dealing with it.

you may say it’s short term thinking, but if you’re optimising for investment, that’s the right thinking. Make money now, you can always move it elsewhere that makes better use of it.

It’s not what I personally agree with, but just my observations so far


With regard to "excessive concern with prettifying minutia", I'm thinking of e.g. code reviews where people spend significant attention going back and forth on minor stylistic issues.

Another example: I remember a coworker reviewing code I wrote many years ago. I came up with a solution that was reasonably simple and workable, but wasn't the "right" way to do it. My coworker complained, I pointed out various reasons the "right" way wasn't practical, and they said something like "yeah but it has to be right" (without suggesting any concrete plan). Very frustrating -- I don't think it was particularly important code.

Working on my own, I already have a sense of how much effort I want to spend on code quality. When you add code review on top of that, it can feel a little excessive, depending on the importance of the application.

I actually have a lot more memories of code review frustration than code review gratitude. At my next job I would like to experiment more with code "previews" or design reviews -- that seems more efficient than rewriting code which already works.


I can relate very much, from both viewpoints!

I sometimes catch myself discussing “correctness” in PRs because it’s important to know what tradeoffs you’re making, and whether a neater/simpler/better solution exists. So yea, sometimes my suggestions can be misinterpreted as blockers.

I have since learned that giving actionable feedback is the trick to smooth review process, as well as trusting the authors (in a way). Their implementation may not be the way I would have done it, but I have to ask myself “will it still work?” as a basis for pass.

But I digress, I can see what you mean in your original reply, and agree, that weird “arranging deck chairs on a sinking ship” does indeed happen


I recommend the pharmaceutical industry.

When the study for which you're producing software is only going to conclude in the next 18 months or so, you get to allocate some time for fixes.

The downside is that it attracts people who want to take advantage of this to slack off or just aren't that good at software engineering in general.

I'm currently in the process of clearing tech debt that ultimately lead to hard to resolve bugs and, ahem, staff rotation.

I can spend days on this so long as I report progress on a daily basis.


"Always leave the code you're editing a little better than you found it" - Robert C. Martin (Uncle Bob)

There's no point in refactoring the whole thing. Maybe add a longer comment explaining the logic you had to decipher when you encountered the code. Rename a few variables from foo, bar and baz tom something more descriptive etc.


> There's no point in refactoring the whole thing

Deep architectural/design flaws in a codebase can't always be addressed using a series of small independent changes.


Yes, but that's also not a thing you do on the side with extra hours you have left over here and there.

It's basically refactoring/rewriting the whole part of the system in most cases, which is a full project in itself.


Agreed. The architecture mismatch paper [1] identifies common assumptions that software can make, such as "I own the main thread of control and other modules will do my bidding", that tend to be baked-in from the start.

[1] Garlan, Allen, and Ockerbloom. Architectural Mismatch: Why Reuse Is So Hard. IEEE Software 1994. https://ics.uci.edu/~andre/ics223w2006/garlanallenockerbloom...


> Deep architectural/design flaws in a codebase can't always be addressed using a series of small independent changes.

Not sure that's true. At the extreme end, you introduce a replacement with a better architecture and run it side by side with the old one, incrementally switching over dependents. Of course, that may take more overall work, but maybe the incrementality is sometimes worth it.


I agree, but then you need buffers in the process, which mostly isn't happening in corporate agile land from my experience.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: