Following on from my More Functional ViewModels In Xamarin.Forms With C# I went further to refactor and see if I could develop a solution that was actually less lines of code to write, and overall, I did succeed.
My functional ViewModel basically goes like this:
Here is what the XAML and ViewModel look like in a fairly simple MVVM approach. This is what you might commonly see in any Xamarin.Forms app.
Now here is how my Functional ViewModel differs, from the standard approach.
- Only One-Way Binding is supported from the ViewState.
- When you issue a command, it creates a snapshot at the exact moment the user presses the button, of the values you want.
The ViewModel, while it has a few more class definitions, overall has significantly less code.
- Properties in the View, don’t need to raise the INotifyPropertyRaised event.
- Data that comes through the CommandParameter is set, and won’t change while you are working with it.
If we exclude class definitions, the total character count comes in as:
- XAML = 235
- ViewModel = 278
- Combined = 513
- XAML = 194
- ViewModel = 476
- Combined = 670
This is the comparison of what the user will deal with, obviously there is much going on behind the scenes, but that is framework code, not app code. Hence with functional, the amount of code is reduced significantly, but the amount of XAML is slightly higher.
Benefits of the functional approach include:
- Easier to unit test ViewModel code
- Less ViewModel code, while keeping a similar amount of XAML
- Your ViewModel (Controller) no longer cares about the Views state
- No Two-Way Binding, which could mean minor performance improvements
- Snapshot of View’s state, at the time the user wants an action taken. Which I could say means a more predictable interaction as far as the user is concerned.
If you need a monitor a stream of events from your Page, much like a TextChanged event, you would want to look into behaviors. I use this approach in my regular Xamarin.Forms apps, and you can see an example in Xamarin.Forms SearchBar, in the “results as typed” section.
This is a proof-of-concept and not production ready, and not sure if there would be enough interest to ever turn it into something more. But, its faster, and allows stateless functions, meaning its easier to test, and possibly performance improvements with only one-way binding permitted. Not to mention, easier to understand code, but that is subjective.
Sample code available in my GitHub Repo Functional.
To answer a few questions:
- Why not RxUI – It still duplicates state between View and ViewModel, and doesn’t provide a snapshot at the exact point of action. Rx is mainly there to handle event streams and it still uses 2 way bindings.
- Why not Redux – The need for Actions and a constantly created new app state, seems over the top.
Note: I also pushed forward, and did a Revision 3.
I do have a more verbose way of defining the Command Parameters that gives you full control over what property and element you want to take. This is just an alternative way of doing the exact same thing.
And I even created the ViewModel in F# because, why not? This is also in the GitHub repo. Excuse the probable mess of my F# code, I’m fighting 15 years of OO mindset.