Hello HN,<p>just wanted to put this discussion out there again to help me (and potentially others) to get a more professional judgement of crufty software projects.<p>I think "This codebase is bad, I could do it better from scratch" is a thought most of us had sometimes in our professional carreer, ironically more often as a young inexperienced programmer than later in your career. I guess that comes with a better understanding of the vast complexity of a software project, the respect for value-producing software in production and a less ignorant assessment of your own abilities. Now I am much more reserved to propose a rewrite. However I recently adopted a codebase (and a team) that made me think: When is a legitimate point reached where a rewrite would be actually justified? I worked with it 3 months now and realize:<p>* There is a substantial amount of Hotfixes from apparently inexperienced programmers (mutable global state, arbitrary waiting statements to battle race conditions)
* There is some business requirements that became obsolete (abandoned views, commented out code with no explanation)
* A whole bunch of skipped test suites
* Two outdated libraries, each of which would demand a very substantial refactoring (vue2 with class decorators -> vue3, dropping of vuex as global application storage)
* Generally a missing pattern on how to organize API access, it's pretty much all over the place<p>What I'd like to hear of the experienced people in this community: Did any of you faced a similar situation with a bad codebase? Which steps path did you go? Rewrite or itearative refactor? How did it go? In retrospect, was it a sane decision? Have you been able to identify markers, or a threshold were rewriting were actually the better decision?<p>Happy new year to everyone and thanks ahead!
I tend to favor rewrites over refactors for two reasons:<p>1. Writing code is easier than reading code.<p>2. When a team is "scared" of their codebase, everybody becomes frustrated and confused and nobody takes responsibility for anything.<p>The difficult question is _how_ to rewrite. Here are some strategies I've seen in the past:<p>- The "slow" rewrite: Rewrite a chunk of the code that can be completely rewritten in 2 weeks. Deploy tiny rewrites alongside everything else. New code should not reference _any_ code from the old codebase. Do not try to fix anything in the old codebase.<p>- The "frodo" rewrite: Ask 2-3 devs to go off on an adventure and rewrite the entire app from scratch while the rest of the team maintains the existing app.<p>- The "YOLO" rewrite: Give the whole team 3 weeks to rewrite the entire thing from scratch. Put 1-3 devs on "cleanup" duty, where they polish and test the YOLO code before release. Also consider doing some group "bug bashes".
> I recently adopted a codebase (and a team)<p>Are you in charge? How big is the team? Is it a startup? Is the software making money? How important are new features to make money / gain clients?<p>Usually with a rewrite, you will end up implementing features in both codebases. This can slow you down a lot, kill team morale for those working on the old project, etc.<p>First, move to a monorepo. Put all the old monolithic stuff in one package, and pull out parts of the app into small clean packages going forwards.<p>Then use microfrontend architecture. Implement one page/feature/component cleanly using a new framework with a separate build. If you use Webpack, check out the Federation feature.<p>However, if you want to move to something like Next.js (with the new turboback which is not webpack anymore) then the microfrontend stuff might be more hassle than it's worth, because Next has a more integrated deployment solution too.
I'd generally rather refactor than rewrite, but I've had to rewrite instead of refactor in code bases where the business logic is very highly coupled to the data model.<p>Mostly I'm thinking of Django/Rails types of frameworks where the database/orm layer is scattered all through the business logic and view/controller stuff. It's basically impossible to refactor one or the other separately or any single component of the system without affecting all the others. This is when I think rewrite becomes the only feasible path forward.
Refactor it beyond recognition. Make every milestone so standalone that if the _entire team_ was hit by a bus shit will continue to work. I had the misfortune of walking this path not long ago and the whole project got killed because it was left in a half finished state before the whole original team left it. Months and months of wasted work.
I'm old. I've seen this more times than I can count. There's always a whole lot of assumptions that just never quite pan out as expected, do they ?<p>Rewrites always end up taking way more time and resources than anticipated, and you'll ultimately end up with something that has fewer features and not necessarily considered "better" by your users.
Refactors on the other hand can get you some wins faster, but will probably be abandoned half-way through and as such contribute to the increasing unstability of the code base.<p>But hey, you're a good cookie, at least you're thinking and asking the questions.
I'm sure you can rewrite the codebase cleaner, technically, but can you also pull it off organisationally (long term mgmt committment, sufficient budget, resources, time and priority ?). If you say there are hotfixes by inexperienced programmers, obsolete business requirements, skipped testing etc., you need to ask yourself why that is and how it came to be, and whether you can really pull off a rewrite under the conditions that led to the current situation ?<p>So yeah, I tend to favor refactoring, at least you'll end up with something.<p>Also, applicable xkcd: <a href="https://xkcd.com/927/" rel="nofollow">https://xkcd.com/927/</a>