Tactical or Strategic? Why not both?

In most engineering discussions there's likely going to be a point where there's a trade-off to be made, do we solve this now, short term, or do we wait for a more thorough solution to be implemented.

I believe it's always a good idea to outline all the options available to us before making a decision like this and that requires time to look at the problem and come up with different approaches.

Not all businesses can afford engineering to take the time needed to do the thorough work, deadline pressure is real and often leads to finding a shorter term tactical solution and adding the strategic options onto an ever-growing list of tech debt.

What might this look like?

Imagine an Order processing service which handles orders and deals with making sure the payments are being processed - something you might find in most businesses (though if a business is small enough they may rely on a third party for this but the idea is still the same).

As an example there could be a bug in the JavaScript codebase that cause a production outage. This bug is something small like accessing an undefined property that an engineer assumed would defined at runtime.

Below is a sample of some JavaScript code where an activeOrder is being read for an id and assigned to another variable orderNumber.

const orderNumber = orderBook.activeOrder.id;

On the face of it this is pretty straightforward code and would likely pass code review without much query. However what happens when the activeOrder is undefined?

Because the way we're reading this id parameter we're assuming that activeOrder is always present and that might be a fair assumption to make but there's no guarantees without more robust checking and unit testing.

In the undefined case the code will error with TypeError: undefined is not an object and this could cause real loss to a business.

Late night computer

It's 2am on a Saturday and you've been paged because a recent deployment has changed some logic which has lead to the activeOrder being removed.

Tactical fix

A short term 'tactical' fix would be to use optional chaining on the activeOrder value.

const orderNumber = orderBook.activeOrder?.id;

In this case we at least expect undefined for the activeOrder and depending on how orderNumber is being used elsewhere we'd have to then write additional logic.

Similarly a unit test could be written to cover this negative case in the future and harden our code.

Strategic fix

However, throwing in a unit test and optional chaining is a reactive fix to an issue and solves only the issue in front of you.

A more strategic fix could be to add TypeScript to that file and its dependencies in order to protect against this type of issue in the future.

Is the trade-off worth it?

Though the above example is fairly contrived I have seen it play out a number of times in production code. Eventually the short term fixes pile up until there's a web of spaghetti that no-one really fully understands and folks joining the team have a hard time ramping up.

With that in mind, no, it's almost never worth it and creates more work in the long run.

Creating a ticket, TODO or note on the specific issue detailing the tactical / strategic options and making sure everyone is aware of what was done, is the first step. The next is doing the follow up work.

In the case above the TypeScript migration might be a huge undertaking (and in this specific case there's help) but it will always pay dividends to prioritise the strategic fix.

Getting buy-in for the follow up work might take some convincing, for production issues a good postmortem can help align everyone and get everyone thinking about the problems (even better if you can demonstrate the actual cost to the business). A good write-up of the ongoing issues, grouping similar cases will add weight to the idea that a more strategic fix is needed.

After a certain point though this becomes less of an issue of doing a strategic fix and more of one on coping with tech debt... which is a topic for another day.

I hope you enjoyed this, as ever you can reach me on Mastodon (or Threads if that's more your thing) where I'm always around to chat about all things software engineering.

First appeared on Trusty Interior, last update 14 Nov 2023