This blog post is based on some of the experiences I've had working with on different cross platform apps with Xamarin.Forms.
One of the biggest problems when writing cross platform code that should work on multiple platforms is that you have to choose an architecture and some patterns and stick with them to avoid ending up with code that is hard to maintain and hard to extend with new features.
The architecture and patterns you choose needs to be easy to understand and extensible enough to support future features.
Patterns
My most important principle is to build n app based on loose coupling through dependency injection and then to use the service locator, messaging bus and mvvm patterns to implement the functionality and user experience.
Combining this with unit testing enables me to develop new features quickly while keeping manual testing to a minimum.
As a rule of thumb I always write my business logic in service classes that can be configured and injected in my view models. These classes are also testable using a unit testing framework like NUnit.
Its common to have a dependency on a cloud service. Such a service is often exposed as a REST based API that can be accessed over HTTPS. Usually I wrap services like this into simple client classes that can communicate with the server and that can be used by my services (never use clients directly in your view models!).
To accomplish this I use the HttpClient library from Microsoft with the modernhttpclient NuGet package to get native speed and performance. For serialization I use Newtonsoft Json.
If you have the need for local storage there are many options. I'm using SQLite.Net/SQLite.Net Async since it gives me full async/await support and a nice little ORM that can be used with c# classes. For simple storage needs you can always use a file based library.
I'm using regular resx files for localization - these work as expected under Xamarin Studio. (you might need to create the localization project in Visual Studio, I've had some issues creating them in Xamarin.Studio - this might have changed by now).
The mvvm pattern is my default choice for wiring up the business logic and the user interface in my apps. Using ViewModels that transforms data from my services to properties and commands in my view models makes it really easy to get the user experience right. Xamarin.Forms views supports data binding to the view model's properties and commands.
I almost always have the need for some custom UX in all the apps I'm working on. In Xamarin.Forms you have some excellent extension points called custom renderers that act as bindings between the abstracted and native user elements.
If I have smaller needs like drawing some shapes and/or lines I usually add the NControl library to my project. It lets me create custom controls using the NGraphics abstraction layer. The NControls library is written and maintained by me, you can read more about it in a blog post here.
Remember to create an abstraction layer for tracking and error reporting so that you can plug in your own favorite library.
- Try to keep the level of customization at a minimum - it is expensive and time consuming and adds to your maintenance costs
- Follow your patterns - don't be tempted to write business logic in your view models or views
- Refactor often
