ViewModel-first approach in Xamarin forms

There are primarily 3 patterns to choose when developing mobile applications. They are MVC, MVVM and MVP. For a detailed discussion about them check Xamarin application architecture.

The focus of this post will be around MVVM pattern. One of the earliest and most stable MVVM libraries for Xamarin has been the MVVM Cross library Like most libraries, this also followed a ViewModel-first approach. What this means, that the focus of the developer is always on the ViewModel and the data in the application. All transitions and animations are also data dependent, which means a user moves from one ViewModel to another and not from one screen to another. It’s quite a capable library but suffered from certain limitations, such as no preview in Android layouts due to embedded binding information in ‘.axml’ files, no header view for listviews etc. Also, to use this, developer requires native UI development experience as well. That being said, it is still quite a capable library and most applications can be written using this.

Xamarin forms, on the other hand, allows better preview of UI, even live updates (using live player). Most developers with ASP.net and XAML experience and without any mobile experience can start writing mobile applications targeting Android, iOS and Windows. However, it is a UI-first approach, which means, the developer is concerned more about UI and data becomes secondary.

Below we will look at a way of ViewModel-first approach in Xamarin Forms, allowing developers with XAML experience to quickly start writing mobile apps. The complete application can be downloaded from here ViewModel-first xamarin forms sample

First is our BaseViewModel

ViewModel-first navigation

Next is our main contract for navigation within the application

The implementation of this contract will allow transition from one screen to another, by only providing the ViewModel’s type and optional parameter.

In the sample application, Autofac is being used for IoC. For more information check it out here.

For implementing the ViewModel-first approach, we will use an anti-pattern, that is Service Locator. It is labelled as such because of the complexity of resolving dependencies when the code base is quite large, and it only works well in simple scenarios. This is exactly the case with a View and it is ViewModel. In most applications, each view will only have one view model, and each view model only caters to one view. Thus, this pattern becomes a perfect candidate for this situation.

Service Container with IoC

Below is the code for AppContainer.cs, where we register all services. Note the mocked services used for Automation. For more discussion about Automation in Xamarin check out Enterprise testing in Xamarin.

The LoadViewModel method is utilised for locating view model for a view.

A BaseView class is created, which acts as the parent for all views inside the application and takes care of loading its view model as shown below. This is where we use Service locator pattern to load ViewModel for the view.

Implementation of ViewModel-first contract

Below is the NavigationService class that implements INavigationService contract.

UI transition using ViewModel

In the sample application, we have search screen and a result screen. Using above service, we can move from Search screen to the result screen using the code below.

Thus, using Service locator pattern, and an IoC type service container we are able to develop mobile applications in Xamarin Forms using the ViewModel-first approach.

 

Enterprise-ready testing in Xamarin

As focus moves towards mobile-first development, enterprise developers should also focus on automated testing. In an enterprise setting, we like to test for merge conflicts, sync issues, authentication failures, etc and we need to test this on hundreds of devices.

In this post, we will look at how we can set UI test project and application code so that we can test against scenarios that we face in a real-life situation (no connection, sync issues, authentication failures). We will achieve this by utilizing mock application services in the application. The project is a Xamarin Forms application, where most of the application code resides in a .NET Core project. It does not matter which application pattern we use, e.g. MVC, MVVM or MVP.

In a basic unit test, we test various method of a library by mocking all services that it might depend upon and check against expected behaviour.

In UI tests, our aim is to check that UI layout works across multiple devices, and the fact the data displayed by the view is correct. We also check that the application behaves as expected in scenarios such as password expiration, where there is no connection, a failure to get device location etc. Using the same principles as above, we should be able to simulate multiple conditions/data sets for the UI and test against expected results.

All of the code for the below application is available for download at Sample UI Automation.

MOCKING

The first service to mock will be a network service, i.e. a service that is responsible for interacting will back-end APIs. Like any other project, we have a basic network service contract inside our application, defined as:

Assuming we already have an implementation for the above service called NetworkService (along with its unit tests), we are going to add a mocked service. The below code works in 2 modes, RECORD, and MOCK. In RECORD mode, the service acts similar to a real network service, but also saves those interactions (mostly JSON/XML payloads) to a file. These interactions are then used to replay the scene inside a UI test.

 

The RECORDING mode is used with an Android device so that we are able to save the file on the file system and retrieve it using ADB shell tool.

Project Setup

Before we use the above service, let’s define a new configuration for our solution called ‘Automation’.

Right click on your project solution and click ‘Options’. Then under Build -> Configurations, select the ‘General’ tab. Now Click ‘Add’. Enter the name as ‘Automation’. Do this for each platform i.e. Any CPU,  iPhone, and iPhoneSimulator.

Screen Shot 2018-04-23 at 3.29.51 pm.png

Now go to your main iOS and Android projects and define symbols for ‘Automation’ configuration. Here I have added ‘ENABLED_TEST_CLOUD’ and ‘AUTOMATION’.

Screen Shot 2018-04-23 at 3.40.00 pm.png

For this project, we are using Autofac for IoC. When the configuration selected is Automation, the mock network service will be injected into the application.

The mock service, in the RECORDING mode, behaves like the real service and also save those interactions. After loading the service, all that is left to do is test your screen manually. Once the manual testing of the application is finished, we should be able to retrieve the MockRecoding.json file (name defined in the service above) from the Android device. This file will have all the data that we will need while writing our UI tests.

Retrieve the file using ADB tools as shown below

Screen Shot 2018-05-03 at 10.56.33 am

Here is the structure of the recording that we have saved.

 

Screen Shot 2018-05-04 at 9.03.05 am

Backdoor methods

Next, we will see how we can use the above-saved interaction file and use it in our tests. UI tests are mostly commands that we send to the application, such as button clicks and gestures, and we then test the UI for expected results. We need to write backdoor methods in our application that we can later invoke from a UI test.

Below is a ‘LoadApiData’ method, which injects data into mock service using its exposed public methods. Again, this code only works when the selected configuration is ‘Automation’.

Consider a scenario where we swipe down a list view to refresh it. For testing this scenario, we want to first set the data that the list initially has, then we will want to set the refreshed data, then perform the swipe gesture, and finally check that the list has the expected data in it.

Add the recording file that we saved earlier inside a folder in our UI test project. To use the above recording, add it to your test project inside a folder named ‘Data’. Then right-click on the file and set its ‘Build Action’ to ‘EmbeddedResource’. For more about the embedded resource, check out this blog.

The test can be as simple as this. Note how it uses the backdoor method before moving to list screen. Using Xamarin test cloud (now App center), we can run the below test on hundreds of devices and check for UI specifics.

With mocking and utilizing test cloud we are able to able to test the same scenario on hundreds of devices. Not only that – since we are mocking it, the same MockNetworkService can be used to perform development too, such as when APIs are under development. All we need is the JSON payload, and we can manually edit the recording file.

 

 

 

Xamarin Application Architecture

In this post, I will talk about strategies for developing a cross-platform Xamarin application with a focus on code sharing, increasing testability, and reducing overall development and maintenance efforts.

The application architecture is itself problem specific, but there are certain design patterns that can guide the overall structure of the application. The ones I mostly work with are Model-View-Controller, Model-View-Presenter, and Model-View-ViewModel.

MVC should be adopted for small applications or proof of concept. Since Android and iOS both natively support MVC, it will mean fewer roadblocks and faster implementation.

MVVM reduces platform-specific code, and most of the logic is shared across platforms using PCLs. There are great MVVM frameworks out there that work really well with Xamarin, such as MVVM Cross, and the official Xamarin Forms.

MVVM Cross is a data-driven pattern, and the presentation logic is centralised. This means any upgrades to the library or to the system, can break custom navigation and screen transitions within the application. As Android and iOS platforms are constantly upgraded, with newer restrictions around security and permissions (background tasks/app permissions), and as the user interface (gestures/notifications / newer design guidelines) are greatly improved, support for these can be costly in both time and effort. That being said, it is still a very powerful platform, and most applications can be written with it, with great results.

Xamarin.Forms is a UI first framework and allow .Net developers to use their existing XAML skills for developing mobile applications. Check Data-first approach in Xamarin out to use Xamarin Forms in data-first approach. \However, this platform is still maturing and needs to reach a more stable stage. Even though native controls can now be used in XAML, but one loses the advantage of data binding, and the extra effort required to maintain proper navigation in the application, and catering for various screen types, outdoes the benefit for now.

MVP is another pattern that works really well with Xamarin cross-platform applications. It is a variant of the MVC pattern and allows full use of platform native capabilities, with great control over the UI of the application. It is the pattern of choice for native development and we will look more into it below.

MVP has 3 major components

Model: This is data that we want to show in our views. Apart from data classes, this carries responsibility for retrieving, storing, validating advanced datasets, and advanced functions such as syncing and conflict resolution, cache maintenance, offline capabilities.

View: This module is responsible for showing data to the user and responding to user gestures and actions. It should only be dependent upon the presenter and native platform capabilities for styling.

Presenter: Presenter is the layer below the view and is responsible for providing data the view can use. It relies on the model layer to retrieve data, and can also publish other events to UI, such as loading data state, timeout and error state.

The golden rule of mobile development is to keep the UI layer as dumb as possible. That means UI only needs to know about its data, view transitions and animations, and publishing interaction events, such as gestures, button clicks. As the mentioned view is completely dependent upon presenter, and presenter is dependent upon the view of human interaction. However, to promote unit testing for each of the modules, presenter and view need to be decoupled.

To achieve this, we can define a contract between the presenter and the view. For a login screen the view’s contract can be:

and the presenter contract can be

The presenter should be platform independent so that it can be shared across different mobile platforms. This means it does not respond to UI life-cycle methods unless explicitly told so.

The controllers in iOS and Activities in Android are never directly created using the constructor, which means that we cannot use dependency injection to provide a presenter to our view. In this scenario, I like to use an anti-pattern called ‘Service Locator’.

Service locator is considered anti-pattern because of the complexities of managing dependencies, and dependency’s child dependencies. This is highly error-prone, but in case of multi-threaded programs, where the start of the application can run many different initialisation threads, duplicate instance of a service can be created. This pattern works well in simple scenarios and this is exactly what we are trying to solve. A dependency service can be used to locate the presenter implementation inside the view.

If the scenario was anymore complex, it certainly means, that View has been assigned more work than it needs to perform and is against MVP principles. A sample of this is shown below

As shown above the AppDelegate in the application loads all the presenters in the application. When the view loads, it uses the service locator instance to retrieve its presenter.

By abstracting the presenter from the view gives us many advantages.

  • One presenter will not work on all devices. Such as finger print functionality for login can only be used on devices that have the required hardware. In case inheritance can be used to create versions that can handle extra features while having no functionality in base presenters.
  • By abstracting the creation of the presenter outside the view, allows to make our UI really passive, and thus we are able to test UI independent of any other module.
  • This method allows to create presenters that can help automate UI testing, performing common testing scenarios automatically. This can also be used for automatic product demos.

 

The above implementation of MVP suffers from one disadvantage. It ignores the asynchronous nature of the mobile applications. Both Android and iOS are quite capable devices. Even a simple Notes application performs a lot of activities when loading. These can be logging in the user, loading the notes from the cache, syncing down any notes created on other device, syncing up any notes created during offline mode, resolving conflicts, showing progress to the user, restoring the state to what it was when the application was last closed. These activities can take from few milliseconds to few seconds. The longer the application takes to boot up, the higher the chance that the user will stop using the application, and will eventually remove it from the device.

Enterprise applications are much more complex. In a perfect world, they are developed using mobile-first approach. However, not all companies can follow this and instead of the application interacting with a unified set of APIs, it ends up interacting with multiple legacy systems, combine the result and then provide it to the UI layer. This means that the application load time can be really high especially if there is stale data on the device.

In such a scenario, instead of defining contracts between the presenter and view, a more reactive approach can be used. This allows us to build application with a user centric approach. This means we think of how the user is going to interact with application, and what does the user see while waiting for data to be available in the application. The code below shows this for a login screen.

The above code shows the asynchronous nature of the View, and it follows a push approach, reacting to events when raised by the presenter. This further decouple the bond between the view and the presenter allowing for easier testing, and also helps to identify real life scenarios within the app, such as data being delayed or no connectivity.

Thus, we see how MVP aims at building a very user centric app, with a very passive and light UI layer. Both iOS and Android platforms are competing to enhance user experience. In future, we can see apps that will react and adapt to user habits using machine learning. This also means that they will have to work in a stricter environment, like stricter guidelines for UI, background tasks, app permissions, reduced background tasks, and change in application notification patterns. MVP will definitely allow to handle these changes, without affecting user experience.

Mobile-first development with Xamarin

 

Modern application users have high expectations for applications, even for in-house enterprise apps.  IT leaders realising this have adopted a mobile-first development approach, which ensures great user experience, reduce overall development and maintenance cost. In this post I will provide an example of a mobile-first development project for an enterprise application.

 Business case

A retailer is using Windows CE devices for performing daily tasks in it stores and is planning to move to the latest Android / iOS devices. Each particular task is performed using a single independent application, developed with different technologies (.Net Compact, C++), and each application communicates with many different back-end services and systems.

Apart from maintaining applications on variant technologies, the company also spent heavily on training employees to use these applications.

The road ahead is to develop these applications for Android powered devices.

Road ahead

The application was initially to be developed only for Android, with a future scope of developing a similar iOS application.

The company relied a lot on the daily activities performed through these applications, which meant that these should be powerful and simple enough for end users, minimising training and update costs.

Xamarin was chosen as the development platform, for the fact that it will prove beneficial for porting later to iOS, single code base with C# language (fully matured async patterns, better type-safety, front and back-end teams work more collaboratively), and also, it can realise the full potential of the native platforms (native UI, Geo-location, Notifications).

Mobile-first approach

Mobile-first approach in enterprise means allowing user to perform complex tasks, with ease. This means interactive and intuitive UI, build around the use-case of solving a problem from a user perspective. This also means developing new infrastructure and services that cater for specific use cases in the application.

Consider a case when the store manager of a hardware store wishes to order new stock for an item. This previously involved getting following information:

  • Current store stock
  • Stock availability for delivery
  • Back store capacity
  • Shelf capacity
  • Upcoming sales
  • Pending deliveries
  • Pending customer orders
  • Wasted / discarded stock
  • Understanding of stores’ sale patterns (daily / seasonal / monthly)

 

Some of the services interact with the in-store server, some will require the central server, and a manual review of previous orders, while some of the tasks are completely dependent on a person’s experience. The final task is to manually calculate the final stock to be ordered.

With the new system, a scheduled task interacts with all of the above services, uses machine learning (items bought together/ customer ordered / quantity etc.) to find out sale patterns, cache results daily and in case an order needs to be placed, pushes a notification to the user who has the authority to submit orders.

On the application side, the user can interact with the notification, review the order and submit or cancel with just 3 clicks.

Thus, focusing on the user-first mobile app, made a complex task very easy and efficient for the user.

Additional use case: An item in a store is to be recalled, or is towards the end of its life and needs to be discarded. Since the new web service caches all of the data every day, a new service can be added, that identifies such products and utilises the existing notification module to notify the user.

The mobile-first development can turn a ‘pull’ experience into a ‘push’ experience – making use of mobile platform features like push notifications. With powerful services in place, new functionality is easily added greatly improving store operations.

Code-sharing

The application was designed using Model View Presenter (MVP) architecture. In this pattern the presenter layer acts as the supervising controller for the view. The view itself is quite passive and is responsible for displaying the data provided to it by the presenter and to route UI interactions to the presenter. This allows for moving most of the logic into the presentation layer. The presentation layer is shared across platforms reducing platform specific code. Test coverage is also greatly improved as most of the presentation code is shared.

Use of Xamarin combined with MVP architecture allowed for more than 95% of the code to be shared across different platform, with emphasis on Unit and automation testing. This is evident from the fact that the whole project was delivered in under 9 months and the iOS application was started in the 7th month, and delivered with the Android app.

The components of the application were broken into individual packages, so that they could be used for all future enterprise or customer facing applications.

An excerpt from the OrderService shows how a sync component (LiveDataService) written to work with a live database could be used for a consumer application as well. In below case, it will notify user of current promotional stock.

It is also worth noting here that the use of Xamarin allowed for sharing components between mobile and back-end systems (as separate NuGet packages). This was the case with custom synchronisation framework, model classes, ORM components, utility libraries etc.