Onion architecture with Xamarin and PCL
Posted on May 25, 2014
Over the short history of Xamarin, there has been a bunch of different ways to share code between platforms, when using Xamarin to create IOS, Android and Windows Phone applications. At first, there were only simple ways to share code, like file linking where the developer had to drag and drop files from one code project to another. If the shared code needed to do anything platform specific, the code would need to be filled with #IFDEF statements to target each platform.
This approach is problematic: If the code that needs sharing is spread over multiple files, all the files has to be linked – and most projects would have a high number of files all needed to be linked. Another problem is the IFDEF statements. It is basically a violation of Separation Of Concerns, when a class can handle multiple platforms. In stead the code should be separated in different classes and the dependency framework should inject the proper code for each specific platform
Portable Class Libraries
Near the end of 2013, Xamarin announced support for Portable class libraries in cooperation with Microsoft (http://blog.xamarin.com/pcl-projects-and-vs2013/). The Portable Class library (PCL) makes it possible to share an entire assembly using the same project referencing techniques known from other platforms like web and windows projects. Just create a PCL assembly, add your shared code, add unit tests etc, and then reference the project from your main application or another PCL library.
When creating a PCL project, you have to choose a profile for the PCL. The profile basically describes which platforms the PCL should target. The more platforms you choose, the more restrictions you will have on the .net framework features available. If you for instance choose to target Windows Phone, the PCL will not be able to use HttpClient directly.
Onion Architecture
Onion Architecture was originally described by Jeffrey Palermo back in 2008 (http://jeffreypalermo.com/blog/the-onion-architecture-part-1/) and it has a history going even further back. Its a widely recognized architecture when using domain driven development and IOC.
The architecture describes a core which only contains a domain model. Around the domain model, there is a bunch of domain services, who knows the core. But the core has no knowledge about the domain services. So all references goes from the outside to the inside. The next layer is application services and UI / infrastructure. The UI is kind of self explaining, but the infrastructure needs a few words.
Lets say the application needs to read information from a file. In stead of placing this functionality directly in the domain services, the service will provide an interface and code against this interface. The actual implementation of the file writing functionality is placed in the infrastructure layer and injected into the domain service layer through the use of IOC.
Given we want to retire early, I want to create a competitor to Instagram and sell it to Twitter for an insanely large figure. But I will start simple though. My app will only be able to capture an image and save it to disk.
My domain model (core) would look similar to this.
namespace MyApp.Core.DomainModel { public class Image { public Image (byte[] imageData) { ImageData = imageData; } public byte[] ImageData { get; private set; } } }
The domain model is simple and reflects my only domain which is the image.
I need a domain service to actually capture images and store them somewhere. But as this is platformspecific and uses infrastructure that is different on each platform, I choose to implement my domain service as an interface.
namespace MyApp.Core.DomainServices { public interface ICameraService { MyApp.Core.DomainModel.Image CaptureImage(); void SaveImage(MyApp.Core.DomainModel.Image image); } }
Another important benefit is, that my app, so far hasn’t decided weather the image should be saved as a file or posted to an online account. All this depends on the implementation of the interface.
On top of this simple domain model and service, I will provide my most outer ring of the onion. Off course I provide a UI for IOS and another for Androind. But I will also provide an implementation of the ICameraService, that will actually capture images on each platform.
The result is that all code that can be shared, is shared and platform specific code i separated between the platforms.
I will end up with a solution looking like this (ooops… forgot my unit-test projects)
Why is Onion Architecure such a great fit with Xamarin?
Xamarin gives the advantage, compared with other x-platform tools, that you can share native code between platforms and only provide platform specific code for the parts of the code that differ for each platform. This model fits perfectly with the onion architecture, where all code in the inner circles of the onion is general and can be shared between platforms. The code in this part of the onion should never contain platform specific code and even the most restrictive PCL profile should be useful for this.
There is a bunch of solution templates available for making Xamarin based apps using the onion architecture. Take a look at these links and try it out.
https://github.com/Kizmar/xDriven
https://github.com/OSTUSA/xdriven
_