How to find the cause of an exception in async code

  softwareengineering

I often see myself trying to follow my own code to find out where the exception came from.

The typical example is when some parsing fails, and I catch the execption. Then I spend a ridiculous amount of time using breakpoints and step-in / step-out / step-over to see the exact parsing that failed. Because many methods and many different calls use that specific parsing, and I can’t know for sure which one caused it.

Right now, if it’s production code that is “solid” and there is one bug coming every once in a while, I really really struggle finding it just by reproducing and jumping every line one by one. And for what it’s worth, even if it always works out, it’s just so tedious.

Is there something I’m doing wrong? Maybe my architecture is wrong? I don’t really have any code to show, but if anyone else ever felt the same or knows by experience this happens, I would be glad to learn something!

6

The fellow who designed the system before I came here included a “Unit of Work” object that could hold a result of the async operation (a Type T) and any errors that occurred, including exceptions and stack traces.

That said, I’m not exactly a fan of his architectural style; it is too complicated, and I have my doubts about the effectiveness of putting async everywhere.

So here are my suggestions:

  1. Implement async only where you know it will make a difference. The primary use case for async functionality is to keep a UI responsive. For long background operations unrelated to UI, there are better mechanisms. Don’t implement async just because you can; make sure you’re getting a benefit in exchange for that additional complexity.

  2. Write code that is unit testable. If you can prove that the code will work on its own as a standalone function, then it will also work in an async context, and you won’t need to go to great lengths to debug it in a running context.

  3. Make better use of your IDE’s debugging features. You haven’t specified what programming language and environment you’re using, but Visual Studio has the ability to give you detail about nested exceptions, including those that occur in an async or threaded context.

  4. Become a master at logging. Logging not only tells you when and where any problems occur, but it also trains your mind to understand how the software works and gives you ongoing information about its health.

The most important of these? Number 2. It’s much easier to troubleshoot code outside of async or threaded contexts.

1

LEAVE A COMMENT