Defensive coding practices

JohnHardmanJohnHardman GBUniversity mod
edited July 2018 in Xamarin.Forms

I've just been asked in a direct message about defensive coding, particularly around async/await. I've touched on aspects of this in multiple posts previously, but thought I'd do a quick brain dump in one place here in case it's helpful to other people. I've probably missed some things, but these are the bits that came immediately to mind at approaching midnight after a long day:

(1) Everywhere that your code is called from Xamarin.Forms, the operating system or third-party code, wrap your code in try/catch and report (via a suitable and reliable method) any exceptions that are caught. That includes event handlers, life-cycle methods (OnSleep, OnResume, OnStart), the body of any Tasks that you start/run, custom renderers etc. You should never let an exception bubble up from your code into somebody else's code (unless an agreed API says you can). You may want to create some helper methods to avoid cluttering up the code (I think it was the Xamarin Sport sample that contained some examples of this) - I use such helper methods to catch exceptions without me putting try/catch all over the place.
(2) Add unhandled exception handlers (see https://forums.xamarin.com/discussion/comment/298841/#Comment_298841 ). Minimise what unhandled exception handlers do - popping up messages and waiting for a user response will not work on all platforms. If that's what you want to do, you might want to synchronously save the details and display them the next time your app is started. Attempting to navigate back to your app's main page might sometimes work (or seem to work) on some platforms, but if the unhandled exception has resulted in your app being in an unknown state, then navigation might not work (and who knows what else might go wrong subsequently).
(3) Integrate Mobile Center, HockeyApp, or some other system for reporting any exceptions that get past (1) and (2) (this shouldn't happen once you have comprehensive exception handling in your code other than in very specific circumstances - I've only seen one example). Ideally, you should also use those systems for reporting exceptions that you do catch, but the functionality was missing from Mobile Center and Hockey App the last time I looked (it used to be in the now deprecated Xamarin.Insights). I believe the plan was for it to be added to Mobile Center, but haven't checked recently to see if it has been.

As for async/await:
(4) Other than event handlers, don't use "async void". Use "async Task" or "async Task<T>" instead.
(5) Don't use async methods inside life-cycle methods (OnStart etc).
(6) Always await async methods (unless you have a very good reason not to).
(7) To make bugs easier to identify during code reviews, postfix the name of any async methods with "Async" (so an async version of PlaySound would be PlaySoundAsync). That allows you to easily spot any async methods that have not been awaited.

And thread-safety:
(8) All the things you would normally do to make C# thread-safe, with the addition of only accessing UI objects from the correct thread. Use Device.BeginInvokeOnMainThread if code on a different thread wants to update a UI object.

And generally:
(9) Controversial one: rather than avoid async/await, embrace it. Your codebase will be easier to enhance in future if you don't have to refactor the entire call tree because you have to add an async method deep, deep down in the call tree.
(10) If building your code results in warnings on warning level 4, address the cause of the warnings.

Sign In or Register to comment.