I’ve found that applications have a bit of a back and forth to their development over time.
They start out with a specific structure, that meet the original requirements. But as customer use the apps, new features are added, usage changes, new bits of code are thrown in. And over time, the clean design that you started with starts to get a bit hairy. But it still works, so while the code might not win you any awards, neither is there a valid business case for embarking on a major refactoring project.
But eventually, that day comes when some feature request hits the wall of spaghetti that your app has become, and it just isn’t going to stick. Refactoring must be done. You need to rein in your app, get it back under control, make it elegant again.
The way I know that time has come is very simple – when a feature request that should be simple (say, 4 hours of work) becomes 4 days of work, it is time to refactor.
Today is that day. I finished out a new set of features for one of our customers, and realized there there is a gap in the app’s functions – no one has noticed it yet because this is a new app, and not all functions have been running live in the wold for very long. But by my estimate, it will become readily apparent in about 4 weeks, so I decided I should fix it now before it truly becomes an issue.
But to fix this gap, my code needs to be aware not only of who the user is, but by which mechanism they got to the current document. There are 4 ways into a document, with 2 main scripts that load the data. But now I have another data point to throw in, which means each of the 2 scripts needs another variant throw in, with 3 possible results.
And that is now the critical mass that will drive refactoring – 2 scripts that are fairly redundant is not great, but not unreasonable in the grand scheme of things. 6 scripts? That is crossing the line,. It would take more time to write, more time to maintain, and the codebase has moved from “not ideal” to “bad”.
Luckily, refactoring is actually fun. And basic refactoring of scripts doesn’t really take all that much effort – pull out the commonalities into functions or libraries, tack those function calls into the scripts, add variables and logic as necessary to act out the variants in the logic, and we’re done!
With any luck, I will get this all done today, and deliver the feature set for testing tomorrow morning. (I rarely deliver code the same day I write it… more than half the time, sleeping on it makes me realize a few small tweaks that would improve things).