The code is a mess! It’s inefficient and impossible to maintain! There’s no way forward, we need to completely rewrite this thing from the ground up!

If you have spent any amount of time as a developer, this sentiment should seem familiar. As should the subsequent crushing reality that your business partner has neither the budget, nor the appetite for a long, open ended rewrite of software they’ve already paid for. It’s tempting to throw your hands up, just keep adding to an unmaintainable architecture, and wait for “someday” when there will be budget for a rewrite.

Unfortunately, “someday” (usually) never comes. The chances that the business will fund a rewrite anytime soon are slim and clinging to that idea just gives us an excuse to dodge the real and difficult work that’s staring us right in the face. So what are we to do as forward thinking developers and managers?

The first step is to understand that as developers, code quality is OUR job, not the customer’s. Customers do not, and likely will never, adequately value nebulous items like “code quality” or “maintainability.” This gap in understanding is often a point of contention between development and business teams, but there is an up side to accepting its irreconcilability. That is, it frees development teams from seeking their stakeholder’s permission to write good code.

It might sound obvious, but items like “refactoring” and “writing tests” shouldn’t ever make it into a product backlog where they have an opportunity to be de-prioritized, and code quality should never take a back seat to feature velocity. They are really one in the same. Maintaining, or at least working towards a quality code base is a non-negotiable responsibility of developers that doesn’t have to wait for a time budget, or a line item to be created. It starts immediately.

So what can we do if we find ourselves thrust into a project that is already buried under a crushing amount of technical debt? Embarking on a major refactor in the face of feature deadlines, and without an explicit time budget could seem impossible, but it isn’t. The easiest thing to do is to tie a small refactor to every feature you work on. Even if the refactor isn’t directly tied to the feature. Each time you touch the code, leave it better than you found it. These changes add up faster than you’d think.

That approach might work for most projects, but sometimes we need a major refactor that takes some time to accomplish. The key to getting time is to tie the refactor to a product feature that the stakeholders understand, value, and are willing to wait for. Features like performance improvements, mobile compatibility, or 3rd party integrations could be really valuable to your stakeholders, and all of them could be predicated on a significant refactor. If you’re able to promote the business benefits of these features and get stakeholders to buy in, they will be much more willing to wait the extra time because it’s commensurate with the value they’re receiving.

Recently at Levvel, we did some maintenance work on a complex JavaScript application that used WebSql to sync large amounts of data into the browser for offline use. During its initial development, the app changed hands several times between different development teams, leaving it without a consistent, logical architecture. The emergent design was hundreds of thousands of lines of asynchronous jQuery code, no rendering framework, and no centralized data model. The app was a maintenance challenge to say the least and adding new features to the existing architecture was incredibly difficult. To add to the challenge, a major rewrite was completely out of the question.

In our next post, we’ll talk about the steps we took to implement a major overhaul and put this application on the path to health without moving its release schedule.