Architecting a Large Xamarin Forms App

Following on from my LinkedIn article of Adapting to Enterprise and B2E Xamarin Forms App Development, this post will go into how I structure and architect an app, that will have a large code base, and multiple developers. When we are dealing with a large code base, across multiple developers, it’s wise to start favoring control and consistency above initial speed of development. Setting up your CI/CD process, is a must, to gain speed in pushing out updates.

Project Structure

First, lets look at the project structure. Portable Class Libraries, or .NET Standard Libraries are a must use in these scenario’s. Shared code is far too hard to maintain over long periods, with multiple developers. MVVM and Dependency Injection are essential, and while Xamarin Forms comes with these features baked in, it is recommended to use an MVVM Framework. There are plenty of good MVVM Frameworks out there. For myself, and the style of architecture I wanted to use, none of them quite fit as well as I wanted them to. Which is why I created Exrin, and even a template that mirrors this architecture style.

Native Projects

The native projects are kept rather light. I only put Custom Renderers, or platform specific code, that I will use with dependency injection. Any configuration, will be loaded or setup here as well. This may be different depending upon your MVVM framework, and dependencies.

Configuration files are normally kept in the native project, for any platform specific configuration. You may also keep configuration in your App project, for cross-platform configuration. To ensure you have configuration files that are easier to work with Continuous Deployment, have a look at Configuration Files in Xamarin Forms, to see how to set this up. Configuration is then also injected into the app via an IConfiguration object, which is fantastic when unit testing.

App

This is your main starting point, and where the Xamarin Forms Application (App.xaml) will be located. This project has a dependency on Xamarin Forms, and will provide any bootstrapping as required. Depending upon your MVVM Framework, this is normally where I map Views to ViewModels, and initialize the Dependency Injection Container.

Framework

The framework project is a simple library, that contains only definitions, or generic helper code for the entire app. Keeping this project with zero dependencies is key to allow it to be available across all libraries in your app. Think of the framework app, as the generic contracts that allow you to pass data between projects. This project will have NO reference to Xamarin Forms.

Logic

Your main business logic, including ViewModels and Models, will be located in here. The interesting point to note here, is there will be NO Xamarin Forms reference. This is key, if you want an easy time setting up Unit Tests. Inside the Logic app you will also want to include a Service Layer and Repository Layer. These can be branched out into separate projects if you need to, but generally it’s easy to keep them in the same app.

Service Layer & Repository

The next approach I take, when dealing with services, such as connecting to API’s, is to first create an aggregate service layer. This service layer acts as a service that connects with repositories to retrieve the information, from multiple repositories and give them back to the Model. Sometimes the Service layer may simply be a pass through layer, but often its great in combining and manipulating data from various sources to your app. This also means that any changes to the repository are shielded from your app. It becomes increasingly great when you are in control of your own API and numerous modifications are made during your development lifecycle, which were out of your control.

The repository layer is simply a connection to a database, or an API. It gets the data from the source and passes it back to the service layer, for mapping into an app friendly model, for consumption.

View

This project, will contain all your Xamarin Forms views, behaviors, converters, effects and any other UI related code. It is completely separated from your business logic and the two projects won’t reference each other.

While I know its perfectly acceptable to place UI related code, in the code behind of a view, I take a hard line and don’t allow anything in the code behind file. Behaviors, Effects, Converters or writing a Custom Control, is preferable. It keeps your Pages, completely XAML, encourages you to reuse controls, and other UI related code. It also alleviates having to monitor and track which views have code, and if it needs to have a corresponding unit test.

Unit Tests

As important as always, adding a unit test project is essential to quickly spot potential breaking code, as you develop the app. While I won’t go over various approaches of how to code Unit Tests, the unit tests here will only be testing the Logic project of your app. The Framework and App projects should only have bootstrapping code, or definitions. It’s unlikely to contain any business logic. The View project will also have no unit tests, unless you want to test behaviors, or converters. Even so, these behaviors and converters can run code in the Logic app for anything substantial. If your converters, behaviors etc aren’t substantial, you can normally avoid unit testing these.

Because the Logic project is just a standard library, with no reference to Xamarin Forms or native Xamarin, it is extremely easy to unit test. I normally create the unit test as a Full .NET Framework project, and run with xUnit. Though NUnit is also another common alternative.

If you wish to unit test code in your native Xamarin project files, you will need special runners, that some unit testing frameworks provide. However these are normally a little trickier to setup. As such if all business logic can be contained in the logic project, you will have a very easy time.

UI Tests

UI Tests are important to test the Views in your app and complete integration tests between your views and code. I would recommend Xamarin UITest, though developing scripts in Appium is another common approach I have found. Ensure you code the AutomationId on each visual element, and any mobile testing framework will be able to pick up these ID’s to perform actions and read values.

Special Considerations

Larger projects, tend not to work well with certain patterns and technologies. In this case I would advise you steer clear of Messaging Center, or any events that are global in nature. Their interactions become increasingly hard to track when you reach a certain scale. You can read the post Misuses of MessagingCenter to see the various cases against this pattern.

However, I do recommend Reactive Extensions, to handle events between two objects, such as the Model and ViewModel, or within the ViewModel. You can look at an Introduction to Rx.NET to see how it can apply to your project.

Learn More

If you want to see how this architecture works with Exrin, there is the Introduction to Exrin video, or you can download the Exrin Template to try yourself.


XAMARIN.FORMS MONTHLY NEWSLETTER

JOIN 1,100+ SUBSCRIBERS

  1. Don't miss out on updates
  2. The latest info from this site, Xamarin and the community
  3. Unsubscribe at any time*

* We use MailChimp, with double opt-in, and instant unsubscribe

Microsoft MVP | Xamarin MVP | Xamarin Certified Developer | Exrin MVVM Framework | Xamarin Forms Developer | Melbourne, Australia

Related Posts

4 Comments

  1. NMackay

    Hi Adam,

    Another interesting post.

    I’m working on a pretty big app at the moment (9 modules), very similar architecture, the main PCL has the app shell, there’s common shared PCL with common converters, common app services, helper classes such as consuming restful endpoints, anything that’s shared basically, a data lib that has service implementations for each module.

    It’s a pretty similar structure to our enterprise WPF app, it means cross skills transfer can be done internally whenever I move on to a new role and the business won’t be left with some kind of alien app…that’s partly the beauty of Xamarin Forms as it’s all XAML with Unity and Prism but jumping in from a WPF C# app you should be reasonably comfortable.

    1. Adam Pedley

      Modules are a good way to split your app. With Exrin, it has Stacks, which are almost similar in creating boundaries for specific app functionality, but its more logical, rather than physical.

  2. Jeff

    Hi

    Great work on your MVVM framework and this looks like a very good template to use.

    Do you have any samples that use this template? I see your Tesla sample app uses a different template.

    Thanks in advanced
    Jeff