The ViewModel method template

ViewModels are the DDD equivalent of application level services and have two basic three basic responsibilities:

  • Start and manage domain level workflows and transactions.
  • Keep track of the state of the current view (or event the complete application).
  • Translate domain objects and states into a representation that can be displayed by the view.

Over time, we got to some standard for methods on ViewModels, that resulted in a template methods that handle „everything“, and we can then just pick the things we need.

As many Apps represent some server data, ViewModels tend to have a certain set of methods:

  • LoadData/Activate():
    Called every time, a View loads with the ViewModel as it’s datacontext. It makes sure all data is loaded correctly.
  • UpdataDataItems():
    Loads all data, that is currently available.
  • Refresh():
    Refreshes data from the web.

(Yes, these are quite similar to MvvmCross’s init(), start() and reloadState() methods.)

LoadData()

LoadData() is called when a view loads a ViewModel as it’s data context. This methods fill itself with data and (when required) starts a refresh to get the latest and greatest data from some service.

This is also the place to take on parameters that are submitted by the view loading this model.

public async Task LoadDataAsync()
{
    if (!IsDataLoaded)
        await UpdateDataItemsAsync();

    if (NetworkHelper.IsNetworkConnectionAvailable && UpdateTimerHelper.ShouldUpdate("Employees"))
        await RefreshAsync();
}

UpdateDataItems()

This is the common place to pick up all data that is already available: Locally cached items.

Loading the first data is intended to be fast. Is should be available almost at an instant, so the user has something to view and interact with, while the update operation starts in the background.

private async Task UpdateDataItemsAsync()
{
    // Get items from local cache
    var employees = (await _employeeService.GetEmployeesAsync()).OrderBy(e => e.Sorting).ToList();
    Employees = new ObservableCollection<Employee>(employees);

    IsDataLoaded = true;
}

Refresh

Refresh() is actually the first real operation of the ViewModel. Like most methods on ViewModels, it does not have a return type except Task. Usually, they are called from some event handler (like button clicks) which are void returning and therefore cannot really await anything. Updates happen via the INotifyPropertyChanged anyway.

ViewModel methods should never throw exceptions (see: [The exception barrier]). That’s why most of our ViewModel methods look like this:

public async Task RefreshAsync()
{
    // Precondition check
    if(IsDataLoading) return;
    IsDataLoading = true;

    // Preparations
    var cts = new CancellationTokenSource(TimeSpan.FromSeconds(60));
    
    try
    {
        // Run the actual operation
        await _employeeService.RefreshAsync(cts.Token);
        await UpdateDataItemsAsync();

        UpdateTimerHelper.SetUpdate("Employees");
    }
    catch (HttpRequestException)
    {
        _notificationService.Notify(ApplicationConstants.Text_NoInternet);
    }
    catch (OperationCanceledException)
    {
        // Cancelled because of timeout
        if (cts.IsCancellationRequested)
            _notificationService.Notify(ApplicationConstants.Text_Timeout);
    }
    catch
    {
        // Just to annoy developers, until they got all their error cases checked.
        System.Diagnostics.Debugger.Break();
    }
    
    IsDataLoading = false;
}

This is an „all-in“ example:

  • Before running the methods, application level preconditions are validated: Are we updating already?
  • Preparations like task extenders, CancellationTokens, etc. are made.
  • The actual method gets executed.
  • All error cases get handled.
We usually put an extra ´Debugger.Break()´in the last catch clause. This shouldn’t activate at all, but if it does, the developer knows he has some unmatched error cases. Hopefully, it is annoying enough to bring him to handle it. :)
Werbeanzeigen
The ViewModel method template

Architecture in cross platform projects: Overview

When you start reading into Mvvm, you usually find some articles about INotifyPropertyChanged, Bindings, Commands and reducing Code Behind. Once you are past that point, information gets rare.

But there’s a lot more to Mvvm than just these basic concepts. Especially, if you want to span that architecture cross platform with Xamarin.

This series explains a reference architecture for cross platform Mvvm, which we used in several projects. In the coming weeks, I am going into details for all steps along the road.

It all began in the model…

Add a PCL: Project.Sample.Domain

We usually start with the domain model for our app (yes, we used DDD, but even if you don’t’ this is a good starting point). First step is to create C# classes for all of our domain entities like News, Users, Products or whatever there is. These tend to be just dumb classes with a bunch of getters and setters for most cases.

Once we’ve got the things we work with, we start wrapping them some services around them that know how to obtain these models and how to perform operations on them. Until now, our project looks somewhat like this:

xplat_architecture_1_ model

Further reading:

  • [Design considerations for the domain model.]

And then, things got connected…

Add a PCL: Project.Sample.Domain.RestApi

Next, we connect our app to the services. In most cases, these are already in place: Instagram Api, Office 365 Api, some Azure Mobile Service, etc.

What we have to add are the clients, that connect to these services and convert between their data transfer objects and our model. This usually involves Json.Net, HttpClient and a lot of .FromJson() methods.

This is also the point in time to write some integration tests to see if your clients work correctly. Doing that now spares a ton of debugging time later.

xplat_architecture_2_connectivity

Further reading:

  • [Design considerations for service connectors]

Adding some state…

Add a PCL: Project.Sample.Infrastructure

It’s about time we start making a real application out of all those connected services and models we got right here. So now we got to stop thinking in domain terms and move over to application design (no, not those fancy UI stuff yet; but getting close!).

View Models are the next wrapper around our domain: They know how to uses the services, how to handle all the exceptions (yes, ALL of them) and besides that, they hold the “state” of the application.

State means, they know what data needs to be loaded, what has been loaded already, where we can go and what we can do from where we are. Despite of having just such a small box in the architecture diagram, the ViewModels are our real champions.

xplat_architecture_3_viewmodels

Further reading:

 

Fine, can we do Android now?

Add: Project.Sample.Clients.AndroidApp, Project.Sample.Clients.WindowsApp, …

NO! Do windows first. It’s much easier and way more fun. But yeah, this is where you add all your client projects.

We’ve come pretty far already, but clients still have a lot of duties: They provide configuration for all the models, viewmodels, services, clients, etc.; They have to connect the UI with the viewmodels and of course they contain the UI itself.

All that UI stuff are left uncovered here, because when using Xamarin, you are just writing native code with camel cased naming.

Client projects consist of 3 parts:

  • The UI with all its Activities, ViewControllers, etc.
  • Platform specific implementations of interfaces required by all the underlying components.
  • Connectors to interact with viewmodels
xplat_architecture_4_clients

 

Configuration for the services is usually done using a dependency injection container and a service locator.

As connectors, you use Xaml bindings on windows and everything is nice and easy. Value converters are also a part of these connectors. You can use a framework like MvvmCross (mvx) to get something similar to bindings on other platforms as well.

If you won’t or can’t use Mvx, looking at windows’ compiled bindings (aka x:Bind) is a good option: It isn’t exactly human readable, but you can easily write something similar for android and iOS when getting down into their ListAdapters an ViewControllers.

Further reading:

  • [Learn from Xaml’s compiled bindings]
Architecture in cross platform projects: Overview