Inside IO Apps â Building Blocks, App components Part 1
On the last posts I talked about the general architecture and how we handle the app boot process, today we will dig into the different components that we have, what are their responsibilities and how they work and communicate with each other.
We have four main components: View, ViewModel, Controller and Model (App & Platform Services). Â
View          Â
The view component is mostly composed of Views, XAML (AXML, HTML, etc) and code behind. Â It also contains the usual custom UI controls, app resources and basically everything that is seen by the user. Our views have also two extra responsibilities, besides showing and animating content, they must show to the user when an operation is running and display them error messages when it fails. To achieve this, each of our ViewModels has some INotifyPropertyChanged (INPC) properties which the view binds. We simplified the process by using a base class for all views that handles these data bindings and shows the user the error and loading messages.
Our views arenât restricted to a single ViewModel, this means that a single View can use all the ViewModels available or none if that is the case (usually only the splashcreen view). Of course a view that consumes multiple ViewModels information must have a main ViewModel so that it can fulfill the responsibilities enumerated before. With this approach we avoid similar or exact representation of data and operations, meaning that each ViewModel is a container of only the relevant data and operations to its purpose, completely unaware where and who is consuming/calling his data/operations.
This approach of having fine grained ViewModels is a little hard to implement when you are developing an app that is targeting tablets before phones, simply because on the tablets you usually show a lot more info in a single view than on a phone, but when starting from the phone it enables you to develop the tablet version very quickly since everything is well divided and organized. When you are targeting both tablet and phone, you can just do the phone version first and then make the tablet version, but regardless the order, of the versions development, there will always be refactoring. The golden rule is to not be afraid to move things around and aggregate related operations in a common place, even if there are a lot of things to change. The truth is, if you duplicated something once you are probably going to do it again in the future. Finally, if your tablet version needs more functionality that you didnât have on the phone you can just add it on a specific ViewModel, or create another if none of the existing fits the new data/operation. Some good reads for thinking ahead and dividing code is the Open-Closed principle and the Single Responsibility principle .
Small Components
 We have a bunch of smaller, but not less important, components that I would like to introduce before continuing with the main ones, these components are basically the glue between the main components and the user.
Exception Handler             Â
What is the worst thing that can happen to your app when someone is using it? A crash! Besides being annoying it will certainly generate a lot of bad reviews on the market. You should never let your app crash for code that you control! How? Try/catch everything! Even if you donât do anything with that exception (at least always log them). When I said code that you control I meant everything from the views down, ViewModels, Controllers and Model. The app will still crash for âgod only knowsâ reasons like platform errors (no one is perfect), some UI graphics library that you are using, etc. For this uncalled exceptions we usually let them crash the app but always log them, on some of our apps we save the error and ask the user on the next opening if they want to send it to us or if you can (and previously asked user permission) just send it to an analytics service.
On our apps almost all operations start with some user interaction that will call a ViewModel command, which eventually will call a service or a controller. As you would guess our ViewModels are where we catch exceptions, to demonstrate how, the following snippet shows one of our commands implementation.
So you were probably expecting to see some try catch or some RelayCommand implementation but no, our commands result on the return of a method called CreateCommandForUserAction, that in this case has two parameters a Func<Task> and a string. The func parameter is the implementation of the command, the logic that we want to run, and the other parameter I will get to that soon. The CreateCommandForUserAction ends up creating a command that wraps everything around a method called LoadingSafeRun, this one besides calling the func inside a try catch block, it also handles the exceptions by invoking our ExceptionHandlerService.
The ExceptionHandlerService is a very simple and bare exception handler, it basically is a hashtable<exception,handler>, and his handlers are usually just routines that returns some string given a specific exception like:
In some rare cases the handler does more than returning a string but usually the ExceptionHandlerService only delivers error strings so that the user can know what went wrong.
Before going into the next small component, here you have the implementation of the LoadingSafeRun routine.
Reporting errors and ongoing operations
As a user I like to know what is going on, especially when Iâm on my phone with only one app taking the entire screen, loading and error reporting ensures me that the app is actually doing something or that it failed for some reason. (As a developer I always try to deliver the experience that I would like to have.) Remember that second parameter on the CreateCommandForUserAction? It is the loading string that will appear to the user.
Looking back to the LoadingSafeRun routine you can see exactly how we handle this reporting, the loading operations like I said consist on INPC properties that views bind to, so reporting a loading operation is just setting a string in a property. The error reporting is actually divided in two ways, depending if the action was started by the user or not. If it was started by the user we show the error on a message box (dialog on android) so that the user can have a âstrongâ visual representation that something went wrong. If the operation wasnât started by the user we only show some small visual representation, on WindowsPhone we show the error message on the system tray on android we show a quick toast notification.
Navigation
Any app (any real one at least) has some kind of navigation, this navigation can be to some view/control/etc inside the app our to some other app or platform feature. In our apps our navigation consists on in-app view change. The external navigation we usually wrap around a service like IMailService or IPhoneCallService since this kind of navigation usually needs the app to go to background causing it to be deactivated or something similar.
The internal navigation is also a service, a custom app service (platform specific), that knows how to navigate to other views, show popups, show flyouts (on Windows 8), etc. By having a per platform service we can take advantage of all the platform navigation features and also maintain our code portability.
We have two types of navigation, the navigation that needs some kind of data to be passed along and the plain old navigation that doesnât need any data exchange at all. To exchange data between viewmodels we use a Messenger . Our app service always has two ways of switching between views, you have a command interface and a method interface. The command interface is strictly used by the views, as an example, on windows phone itâs not uncommon to see a button command directly binded with a navigation command, this is useful because there are some views that a user can navigate for a couple of places inside the app, and to avoid having a custom command in 3 or 4 different view models, we simply âpublishâ the navigation service instance and let the views handle that. Of course this can be problematic since we are delegating to the view one of the app core responsibilities but by doing this you avoid identical code on multiple view models and make everything smoother and understandable on both view models and views.
The other type of navigation has some data contract that needs to be fulfilled before any navigation can be done, we are thinking on adding this data contract directly to the app navigation service because of pure convenience, but for now we still role with this model.
Finally the other components of our app usually donât have any access to the navigation at all. One rare case is when the exception handler needs to navigate to some view after an error, for instance our FB Pages Manager has a handler hooked up for when the facebook session expires, and when it does the handler sends the user to the login view.
Wrap Up
Our apps have many components, today we explained the ones that really matter, the components that the user actually see and interact. A few tips
Avoid at all costs an app crash, itâs definitely one of the worst things that can happen.
Always report to your user what your app is doing, take special attention to when the operations was started due to user interaction.
Try to tell the users when something goes wrong, why it failed, this will prevent a bunch of email telling you that your app doesn't work.
Next time we will continue with the rest of our components












