NASA Sapce Apps Challenge | Structure
It's been a while since I last posted a blog 😄. I'm sorry for that! However I'll try to be more active from now 😉.
I still would like to talk about how and why we used Xamarin for our NASA Hackathon challenge. We have been using Xamarin for quite a while at our company and with MvvmCross found that we can develop faster or as fast as other or conventional development.
Since Sunny would be Open Sourced, we couldn't use the framework/code we use from our company. We did however use the separation of concerns parts and dividing (somewhat) logic/classes/etc in there corresponding 'Layers' based on the 'Multi platform App Architecture' which can be found here.
I'll start by why and how we are using this structure.
We are dividing the logic we can share between projects in a core project and create a platform specific project for each platform. Which is the 'way to go' when using MvvmCross. Sometimes we go even further and create separate projects for iPhone & iPad or Android Phone & Android Tablets as well. Most of the times this has something to do with the ability to change the navigation and complete look-and-feel of the app. I'm still not sure whats the best approach, however we find that this works for us 😃. This might change with the current iOS 8 changes though.
It's also possible to create a shared core project to allow sharing logic, navigation between different versions of an app. In the core project we are separating everything in their corresponding folder/layer. The core project contains all the code that can be shared between platforms. I'm not particularity fond of using compiler directives for differentiating code for a specific platform, therefore you will not see this. Instead we are using plugins to support all our platform specific needs and create custom ones when needed.
At every hackathon we try something new and in sunny we tried SignalR, code generation, development speed and HttpClient (as a replacement for WebRequest). I'm assuming your somewhat familiar with MvvmCross and Xamarin. Hereby a explanation for each folder for the Core project why we use this and what it should do.
ViewModels
The ViewModels contain all data which is needed by the Views. The Views will never talk directly to the Business layer, always via the ViewModels. A viewmodel will contain some list of items (or a single item) the App's Views can bind to. Usually this list is an observable collection because this makes life so much easier when updating data and views. However with Sunny we didn't have to update data on the fly so we choose not to use observables.
A viewmodel uses an observable object which updates the view automatically when a change to the data occurs. Automatic view updates (via a RaisePropertyChanged) is pretty nice. For example, we are using a SocketHub (SignalR) which sends back messages. Those messages should have been added to an observable collection in the viewmodel which then automatically updates the view (because of the observable pattern). Now we kinda have to do that manually.
Services
The services classes are used for communication with a back-end. Normally no other class outside of this layer (in this case except the SocketHub which keeps a connection to SignalR) will communicate with a back-end/service. A service will be called from the business layer, which will then do something with the returned result. The returned result will be deserialized to a given domain object by the service.
In most cases a service will also handle server side exceptions and return useful results back to the business layer. Calling services is being done with DI (Dependency Injection).
Observable object
In Sunny we didn't use any observables since we could get away with it 😉. Usually an observable class is nothing more than a copy of the domain object, with backing fields and contains some kind of raise property changed logic. We chose this solution a while back for an easier way to update properties in a list and because we didn't want to manually raise properties or re-set values for objects.
We also found out that having a separate class for communication with a back-end and for the views to work very nicely. Also because of JSON/XML (and several other) attributes. However we did needed a nice and easy way to convert a domain object to a observable object and created PCL support for ValueInjecter. Together with a SetField property, which basically sets a field and raises it when needed.
This also means that an observable object can contain custom properties like FullName for a person or other custom ones the Domain object shouldn't really know about. In an upcoming blog post I'll show more about this!
Domain object
A domain is used for communication to and from a service. This class can contain XmlAtributes/JsonAtributes for serialization. And of course other back-end or services related tags other objects don't care about. In a business entity this class will be used for storing data (in memory or on the local file system) and will be given back to the viewmodels. Usually a viewmodel will then convert that object to it's Observable type which will be used by a view.
Sometimes in projects, when consuming XML or SOAP based services, these objects can contain a lot of useless XML attributes which are not that useful for a View. Converting to Observables also removed some nasty bugs we had with XmlSerialization and MvvmCross.
Mappers
Most of the time this only contains a MapperBinder file which maps Domain entities to Observables automagically. A mapper can also contain additional properties which couldn't be mapped or that should be initialized when converting or updating a Observable object. This was unfortunately also not used in Sunny..
Language
Since we thought about creating a multilingual app we would be using language bindings. Unfortunately we didn't go through with it. However both CustomTextProvider and CTPBuilder allow us the use of a language file per viewModel. Which is so much nicer than using hard coded strings in the views, or just one file for all languages.
Both files are from a modified MvvmCross example and are very useful!
Converters
A lot of UI elements can be changed using platform independent converters. They can be found here 😃.
This is more a wall of text and to make things easier I've added this picture! The blue folders are platform specific and yellow is independent or share-able!
Hope you liked it! 😃