How to document a workaround?
When writing code, every now and then we end up in a situation where something outside of our influence isn't working properly. It could be a library we're using, a browser we are targeting or an integration to 3rd party service we're relying on.
Workarounds are hacks
That's when we need to write a workaround. A dreaded hack that solves the original problem in a different way than originally intended. As one example, I recently wrote about an issue in Firefox with dev tools and extensions. I learned a way around and implemented that while waiting for the bug to get fixed, which it now has been.
A workaround has a few important characteristics:
- Its job is to help you keep your application working and functioning
- It's meant to be a temporary solution with as short lifetime as possible
- It should not be refactored away while the original problem exists
- It should be refactored away as soon as the original problem has been fixed
These make it very important that we document the workarounds well. Let's learn how!
Document very close to the code
For reasons #3 and #4 above, it's important to keep the documentation as close to the code as possible. In practice, this means writing a good code comment next to the workaround.
This is the perfect case for when code comments make a ton of sense. (By the way, if you wanna learn about other good uses of code comments, Sarah Drasner's great talk Art of Code Comments from JSConf Hawaii 2020 is a great watch.)
If we don't document it close to the source (for example, if we write it to intranet, wiki or bug tracker somewhere), we risk a developer later looking at it, noticing there's something weird there and attempt to refactor it, possibly introducing a bug.
So let's write our first attempt:
// This is a workaround for a Firefox bug
browser.storage.local.onChanged.addListener(() => {});
Now we've recorded that the code that looks out of place (other than its bug-fixing side effect, it's basically a no operation, empty code that doesn't do anything) is there for a reason.
Without a comment, a lot of developers might end up in one of the two bad situations:
- They might delete the line of code because it functionally does nothing
- They might be afraid to delete it because they don't know why it exists
Both cases are bad because the first leads to needed code being deleted and the second leads to possibly unneeded code to exist and rot in the codebase.
I'd argue that our comment is not great however. Even though it does answer the question "why?" (which is a sign of a great comment), it does not help with the other parts. It doesn't explain what the wrong behavior is that it fixes and it doesn't help us figure out when it becomes obsolete.
Add references to other sources
As I mentioned earlier, this is code we want to get rid of as soon as possible. It's not robust and it's a hack and once it's not needed anymore, it's causing extra cognitive load to those who read it and possibly a performance hit when its run. In this example case that performance hit is tiny but for other workarounds it might be a big trade off.
In addition, it adds unnecessary complexity to our code, making future modifications and improvements more difficult.
To improve the comment, I'd do this:
// There is a bug in Firefox developer tools where storage display doesn't update correctly unless there's a listener attached.
// This bug is tracked in Bugzilla https://bugzilla.mozilla.org/show_bug.cgi?id=1802929.
// Once it's fixed, this line of code can be safely removed.
browser.storage.local.onChanged.addListener(() => {});
By linking to a bug ticket, discussion, documentation or blog post helps anyone who encounters this code in the future. They'll get prompted "hey, you might wanna check out if this is needed anymore" and we can safely remove the workaround code once we can confirm it's fixed.
It's even better if you can subscribe to updates on the bug tracker to a shared email or Slack channel so you'd get immediate notification once situation clears.
I also like to be very explicit in this comment:
- What is the bad behavior it fixes?
- Where can you find more information about it?
- An instruction to remove it (ie. nothing else is relying on this)
What if there's no clear easy source to refer?
Sometimes, there's no clear or public ticket tracker for these kinds of bugs. Usually though, if you found out that it is a bug in the other system/library/tool, you discovered it somewhere. Document that. A blog post, a discussion thread in the bird site or the orange site or whatever it is.
Even if we can't be sure that the original source gets updated as the bug gets fixed, it usually gives us a better starting point to search further.
You can also add mentions of multiple sources, if you ran into them during your initial discovery. It's way easier to find them when you discover the bug, compared to 2 years down the line if the only thing you have at that point is "this is a workaround, don't touch".
It doesn't have to be perfect. Anything you have that you went through during your research while creating that workaround is good. You could also document in there why/how this particular workaround works and fixes the issue.