Thanks for the link, and I agree with your sentiment. I don’t find myself debugging a lot. Perhaps why i neglected the skill. However just today I was getting a null reference exception on a particular line, yet I wasn’t able to clarity what object it was that was null. Seems pretty silly, but it prompted me to try and hone my debugging skills, as I felt the tools where there, I just don’t know how to use them.

If you haven’t already done so i’d recommend enabling nullable types, at the very least it should make your code more robust against this particular error, and may help narrow down where exactly the null is set.

The debugger is important in the immediate stage of coding, but high quality logs will make your life much easier through all stages of the software development lifecycle.

Regarding real-time / system software, all IO must always be wrapped in exception handlers, and every handler must do something in the catch block, if nothing else log the exception, I usually dump the stack trace as well if I’m not really expecting it to reach a particular block.

Multithreading is a minefield, but you can eliminate a whole class of errors (race conditions) by embracing async/await; in these apps avoid side effects at all costs and try to write pure functions only; never use ‘flags’. Use the concurrent collections, and try to avoid locks where you can; if you must, get in and out of the critical block as fast as you can, or you increase the possibility of deadlocks.

Thanks for such a detailed reply, specific to my use case. Really helpful tips.

and also a device simulator down to the byte/protocol level, then you can inject faults and ensure your app can handle them.

I know I should do this, it’s just such a PIA for me since I hate reading/implenting standards so I’ve avoided it. Thanks for the push, I think I’ll make a start on one this weekend.