My small 15-ish employee company has a large legacy codebase written primarily in old Angular.js v1.x.
Those who've had intimate knowledge of the codebase have long departed, and we can't really hire Angular.js v1.x experts in today's tech landscape.
The scale here is around 100k lines of code.
I can’t believe people know the names of these things, I just can’t memorize that.
Here I discussed this today in a LinkedIn comment, and someone else shared the name of this pattern. Regardless of me thinking this is a good approach, I don’t know if you’re “there”, in terms of being ready to start pulling the system apart.
I would start with documentation. Both vertical, and horizontal. By vertical I mean for key functions (and eventually all functions) document how a call propagates through the system. What methods are called, what they do, etc. for horizontal, after a few vertical steps, see if you can start classifying things into layers like storage access, business logic, transforms, UI generation, etc. It may be too messy and smeared around, but at least give it a shot.
Start small, and try to make changes to how something displays. Add a small feature that makes a write to a new field/table/whatever in storage. Be documenting everything. For these exemplar changes, link your document to the change lists. If there’s a small team, divide and conquer these tasks and knowledge share and document the whole way.
Once you understand the system really well, it may be worth identifying the hardest to understand or most error prone area and start figuring out how to isolate it. Does it do too much? Can you carve off an individual responsibility and just move the code, don’t rewrite it. If you can isolate it gradually, it may become easier to understand and fix.
Once you’ve decomposed the worst part, it will likely be easier to organize the less messy parts as well.
Wherever you can, once you understand what something does, add tests. The more you can test individual pieces the greater confidence you can eventually have replacing them. Do not replace anything without thorough testing, and having a plan to revert/redirect traffic.
Why you want to rewrite it needs to be clear, though. The act of reimplementing is expensive, and can carry a lot of risk. Good tests help, but don’t ameliorate the risk. When you finish, in the best case, you have something that works the same. It is a significant investment, which can only pay off if a lot of people save a lot of time extending it in the future. The more granular you make your changes, the easier it is to replace things while continuing to use the system and add features to it. You will not get dedicated time to do the rewrite, you will need to keep adding customer value in the meantime.
Have a list of the work, and track it. Be able to know how close done is. When new feature code is added try not to implement in the existing outdated code, try to make a shunt into that code that calls out to something new. Try not to dig the hole any deeper.
Total rewrites are very dangerous and almost always take longer than expected (or fail completely) -- can you first decouple the system into smaller chunks with well-defined APIs between them?
That way instead of a "total rewrite", you've reduced the problem into a rewrite of 3-5 much smaller chunks.