I largely subscribe to what is described here, and believe sincerely that any piece of work should be an opportunity to do a little bit of cleanup.
Though, one counter-argument in favor of putting refactoring tickets on the backlog is that it can be useful to make the cost of cleaning the codebase more visible to the higher-ups.
This is especially interesting if each sprint you organize to take up the feature tickets AND the refactoring tickets at the same time. If you work in a place that refuses to pick up the refactoring, then indeed the "hidden" approach described here is probably a good way to go.
i had the privilege of working w/ some incredible eng leaders at my previous gig - they were very good at working both upwards and downwards to execute against the "50/50" rule - half of any given sprint's work is focused on new features, and half is focused on bug fixes, chores, things that improve team velocity.
I learned this when a coworker mentioned this to me. Turns out I was doing it without knowing it was a thing! Of course I continue doing it, but it's good to have a short and clear name to give others (specially those that only seem to follow concepts if they have a flashy name)
The ‘Boy Scout Rule’ and Kent Beck’s idea to “First make the change easy, then make the easy change” are probably the two most important bits of advice I received in my career.
I attribute most of my success to following those rules.
And maybe I’m just applying my own biases, but all the best developers I’ve worked with seem to follow those rules as well.
This seems very consistent with the refactoring techniques taught by Sandi Metz (https://sandimetz.com/99bottles). After taking her course, I successfully applied those techniques to good ends and outcomes.
Not sure "refactor in context" is the tool for every single last refactoring job in the universe. Some plumbing changes may be large or systematic enough that they need to be separately planned and applied, especially as explaining "oh I changed the fundamental way we do things, just in passing" can be a hard PR to present. OTOH, since adopting the "in context" approach I have had many fewer refactoring attempts abandoned, and refactoring seems much more logical and purposeful. So it works IME.
The way to ensure good code quality is: have engineers who are secure in their jobs to push back, who get time to develop and benefit from a good reputation, and who feel a strong ownership of the code
Spoiler: AI isn't going to help with any of that. I'm expecting a 'second winter of horrible codebases' (the first winter being when big companies discovered outsourcing)
I've seen so many engineering teams present bad options, on the implicit assumption that the responsibility for choosing the worst/cheapest option is on the decision-maker. And if they are pressured to deliver bad code, an email trail showing that it was the boss's fault will save them.
A good leader/manager will most likely leave the decision up to the team. A bad team will make the wrong decision and probably blame the leader/manager. The main problem here is the performance of the team - but maybe more importantly the lack of ownership of the team (blaming the boss).
A bad manager/boss pressuring the team to make the wrong decisions - yes, in that scenario the main problem is the boss.
Unfortunately, in my experience, there's often talk about one situation without the other (at least portrayed as the only one). Many times it feels like it's too divert blame and guilt, and to defend what is really the opposite situation. Really makes discussing this topic more toxic and a lot less valuable - much more interesting to discuss the nuances!
I like this. It seems obvious, but I’ve seen many different teams struggle with it. There is a lot of difficulty clearing the brush in a way that doesn’t break existing paths and is also repeatable. It takes a team with a vision and dedication to pull it off correctly, not to mention robust tests to ensure reliability.
One thing not mentioned, is that it’s still incredibly slow. There will be a lot of time pressure and bad optics no matter your choice, this is a lose-lose situation without the proper support. The pressure can also make it difficult to not create new brush in the process.
I do this when I can get away with it but I worry that by cleaning one small area I'll find out the hard way that something else was relying on that bit of code being incorrect and I'll have exposed some subtle bug that hasn't bitten us yet, but probably will in some unexpected way.
engineers always want to re write from scratch and it never works.
a tale as old as time - my second job out of college back in like 2016, I landed at the tail end of a 3-month feature-freeze refactor project. was pitched to the CEO as 1-month, sprawled out to 3 months, still wasn't finished. Non-technical teams were pissed, technical teams were exhausted, all hope was lost. Ended up cutting a bunch of scope and slopping out a bunch of bugs anyway.
That's a hobbyist's rule. In industry, every PR should strive to deliver maximum value to the company, which is sometimes achieved by doing as little as possible so you can work down other objectives.
leaving the codebase cleaner than you found it IS creating maximum value to the company because large changes are almost never walking on the knife's edge between "making the codebase better" and "making the codebase worse". Your codebase either gets better over time, or it gets worse. If it's getting 0.01% worse with every PR, that tech debt accumulates at 1.0001*(# of PRs) which grows faster than you'd think.
Having a maintainable codebase is of MASSIVE LONG-TERM value to a company - far too many orgs are paralyzed by mountains of tech debt.
Doing the minimal work possible is fine for 1-off hotfixes or tweaks or small features, but your argument assumes "maximum value to the company" is measured in the span of of a sprint, and it's not.
Cleaning up the codebase incrementally does deliver value to the company as long as you understand "cleaning up" as "making it easier and faster to contribute to, change, or debug in the future" rather than something adjacent to a form of performance art.
thats a largely meaningless response. enforcing a decent and maintainable architecture is potentially of great value to the company. Unfortunately thats a subjective call. I'm sure you've lived through codebases that dont really admit bug fixes or feature enhancements - things that the company knows that it cares about.
as professionals who are invested in the long term success of the company, it our responsibility to bring up concerns about the future, and attempt to negotiate a good compromise between the short term and long terms goals.
Don't refactor anything bigger than a breadbox. Instead, colonize a new territory, and start a new map - with fewer thickets, one hopes. In my experience, this is possible. It's hard, but it's possible. What's good in the old system survives, all the rest atrophies and dies, and new rails carry the project forward.
But, one assumes, you have a running system and you need to keep it running. If not, knock yourself out cleaning up the map. It can't do any harm.
Such a shift isn't easy to achieve, but it is possible. Don't just clean-up. Extend what you can, rebuild what you must, strangle what's left. Don't half-ass it. Product group's sanctioned refactoring is half-assing it. Your responsibility is to the product itself.
In an academic sense this will be a failure, but practically, with a living-system organism you'd like to keep alive, it can work.
Though, one counter-argument in favor of putting refactoring tickets on the backlog is that it can be useful to make the cost of cleaning the codebase more visible to the higher-ups.
This is especially interesting if each sprint you organize to take up the feature tickets AND the refactoring tickets at the same time. If you work in a place that refuses to pick up the refactoring, then indeed the "hidden" approach described here is probably a good way to go.
I learned this when a coworker mentioned this to me. Turns out I was doing it without knowing it was a thing! Of course I continue doing it, but it's good to have a short and clear name to give others (specially those that only seem to follow concepts if they have a flashy name)
I attribute most of my success to following those rules.
And maybe I’m just applying my own biases, but all the best developers I’ve worked with seem to follow those rules as well.
Refactoring – Not on the Backlog - https://news.ycombinator.com/item?id=27473133 - June 2021 (2 comments)
Refactoring – Not on the backlog - https://news.ycombinator.com/item?id=17624558 - July 2018 (1 comment)
Refactoring – Not on the backlog - https://news.ycombinator.com/item?id=8109065 - July 2014 (1 comment)
Not sure "refactor in context" is the tool for every single last refactoring job in the universe. Some plumbing changes may be large or systematic enough that they need to be separately planned and applied, especially as explaining "oh I changed the fundamental way we do things, just in passing" can be a hard PR to present. OTOH, since adopting the "in context" approach I have had many fewer refactoring attempts abandoned, and refactoring seems much more logical and purposeful. So it works IME.
Spoiler: AI isn't going to help with any of that. I'm expecting a 'second winter of horrible codebases' (the first winter being when big companies discovered outsourcing)
It might seem that way, but it isn't.
A bad manager/boss pressuring the team to make the wrong decisions - yes, in that scenario the main problem is the boss.
Unfortunately, in my experience, there's often talk about one situation without the other (at least portrayed as the only one). Many times it feels like it's too divert blame and guilt, and to defend what is really the opposite situation. Really makes discussing this topic more toxic and a lot less valuable - much more interesting to discuss the nuances!
One thing not mentioned, is that it’s still incredibly slow. There will be a lot of time pressure and bad optics no matter your choice, this is a lose-lose situation without the proper support. The pressure can also make it difficult to not create new brush in the process.
a tale as old as time - my second job out of college back in like 2016, I landed at the tail end of a 3-month feature-freeze refactor project. was pitched to the CEO as 1-month, sprawled out to 3 months, still wasn't finished. Non-technical teams were pissed, technical teams were exhausted, all hope was lost. Ended up cutting a bunch of scope and slopping out a bunch of bugs anyway.
Happy to see these "fundamentals" being still spread around
Having a maintainable codebase is of MASSIVE LONG-TERM value to a company - far too many orgs are paralyzed by mountains of tech debt.
Doing the minimal work possible is fine for 1-off hotfixes or tweaks or small features, but your argument assumes "maximum value to the company" is measured in the span of of a sprint, and it's not.
Cleaning up the codebase incrementally does deliver value to the company as long as you understand "cleaning up" as "making it easier and faster to contribute to, change, or debug in the future" rather than something adjacent to a form of performance art.
as professionals who are invested in the long term success of the company, it our responsibility to bring up concerns about the future, and attempt to negotiate a good compromise between the short term and long terms goals.
Don't refactor anything bigger than a breadbox. Instead, colonize a new territory, and start a new map - with fewer thickets, one hopes. In my experience, this is possible. It's hard, but it's possible. What's good in the old system survives, all the rest atrophies and dies, and new rails carry the project forward.
But, one assumes, you have a running system and you need to keep it running. If not, knock yourself out cleaning up the map. It can't do any harm.
Such a shift isn't easy to achieve, but it is possible. Don't just clean-up. Extend what you can, rebuild what you must, strangle what's left. Don't half-ass it. Product group's sanctioned refactoring is half-assing it. Your responsibility is to the product itself.
In an academic sense this will be a failure, but practically, with a living-system organism you'd like to keep alive, it can work.