In a recent Channel 9 show, F# designer and architect Don Syme and Fabulous maintainer Timothé Larivière introduced Fabulous, a community-driven F# framework aimed to build cross-platform mobile and desktop apps based on Xamarin.Forms.
Fabulous makes a new approach to app programming possible by adopting a React-like MVU architecture, says Syme. This approach aims to simplify code and make it more testable and less repetitive. Fabulous adopts the Model-View-Update (MVU) paradigm to replace the ubiquitous Model-View-ViewModel (MVVM) and provides a functional way to describe UIs and the interaction between their components.
Fabulous is not the first framework to adopt MVU, which was made popular by React and Redux, Flutter, Elm, and other projects. The basic idea behind MVU is managing a core, immutable model which represents the UI status. Each time a UI event takes place, a new model is calculated from the current one and then used to create the view anew.
In Syme's view, the main tenets of MVU are it supports functional programming and the creation of dynamic UIs through simple declarative models which are expressed in the same high-level language as the rest of your application. Another advantage provided by such frameworks is they support live coding with automatic UI update when code changes. This is a radical different approach to MVVM, which is closer to object-oriented programming and favours the creation of complex mutable models which are usually edited through specialized designer tools.
Using a static model is a big asset for MVU, since it mixes well with the inherently concurrent nature of UIs. Additionally, since the UI is a direct representation of the model, MVU makes it simpler for programmers to reason about their UIs. Indeed, while MVVM forces programmers to mentally visualize the sequence of state changes that bring the UI to a given state, using MVU programmers only have to think about their model and how it is calculated.
As Syme says, MVU may incur some cost due to its approach of re-creating the UI anew from the model. This is not such a big issue in the majority of cases, he says, since frameworks usually use an intermediate representation that makes many optimizations possible. Still, MVU apps might not be ideal for use cases where the UI shall be updated frequently, e.g., sixty times per second.
This is how you can express a simple UI in F# using Fabulous:
type Model =
{ isPressed: bool }
type Msg =
| Pressed
let init () =
{ isPressed = false }
let update (msg : Msg) (model : Model) =
match msg with
| Pressed -> { model with isPressed = true }
let view (model : Model) dispatch =
if model.isPressed then
View.Label (text="I was pressed")
else
View.Button(text="Press me!", command=(fun () -> dispatch Pressed))
(Code courtesy of Microsoft and Channel 9)
In the snippet above, the update
function is responsible for updating the model, while view
is responsible for re-creating the UI from the current model.
To get Fabulous, install Visual Studio and enable both Xamarin and .NET Core support. Then, install Xamarin.Forms template pack and create a sample project executing:
dotnet new -i Fabulous.XamarinForms.Templates
dotnet new fabulous-xf-app -n SqueakyApp
This will generate an sln
file for use with Visual Studio to create a mobile app for iOS and Android. Command line options are available to control which platforms are targeted. Interestingly, Fabulous is not tied to Visual Studio and can be used with alternative IDEs. Larivière demoed Fabulous using JetBrains Riders in Channel 9 video.
To start playing with Fabulous, its repository provides a number of sample apps, including TicTacToe and AllControls, while additional useful resources can be found on AwesomeFabulous.