UI Command Pattern : Part I
Tags: xamarin, csharp, mobile, dotnet
Published: 2020-09-19 20:23:01

This post is intended to discuss different Command pattern approaches when developing UI user interactions through `ICommand` interface. 

You can follow along with the final code here:
https://github.com/keozx/CleanRx/tree/master/src/samples/Commands

It is important to analyze each approach and the differences among them so when it is adopted within a team is easier to break barriers of adopting one framework or the other or small part of it. Most organizations will stick to one framework but that is seldom efficient when you need the best tool to get the job done. In my opinion, contrary to common belief, mixing up frameworks is actually a good thing, linking and proper dependency management should remove the clutter around having many tools in a single code base.

This post is divided in 3 main sections:
- The framework comparison below.
- Or, you can [skip to the demo requirement here](#setting-up-a-meaningful-use-case).
- Or, you can [skip to the implementations](#commands-implementation).

## Command framework comparison

In the following table I compare different Command frameworks out there, most of them of course are part of a bigger framework but focusing on one small piece at a time helps in making the right choice on your current situation. 
I chose to analyze what I think are the frameworks most commonly used, I'm missing MVVMCross for now as well as others, but I'll add them in following posts as soon as I have time to play around with them, in this first part I have included only these 4 approaches with the features I found relevant to consider, but this can change later and will update the post and code accordingly.

A better visibility version can be found in my [GitHub Page](https://keozx.github.io/CleanRx/ui_patterns/#command-framework-comparison)

Feature | XF| Prism | Async | Reactive
------------------- | --------- | --- | --- | ---
Executes a simple bindable Action | ✔️ | ✔️ | ✔️ | ✔️ \<T\>
Create from Task\<T\> (not async void) | ❌ | ❌ | ✔️ | ✔️ 
Retrieve unhandled exceptions | ❌ | ❌ | ✔️ | ✔️ 
Observes boolean changes for "CanExecute" behavior through INPC (not RaiseCanExecute) | ❌ | ✔️ | ❌  | ✔️ *WhenAnyValue
Observes IObservable ticks for "CanExecute" behavior | ❌ | ❌ | ❌ | ✔️ 
Guards against double execution (double tap) | ❌ | ❌ | ❌ | ✔️ 
Returns a \<T\> result at end of execution | ❌ | ❌ | ❌ | ✔️ 
Accessible "CanExecute" state | ❌ | ❌ | ❌ | ✔️ 
Accessible "IsExecuting" state | ❌ | ❌ | ❌ | ✔️ 
Subscribe to Completion and executes handler for \<T\> result | ❌ | ❌ | ❌ | ✔️ 

### Xamarin.Forms `Command`
Based on above comparison, is there any reason to use XF Command? well only for a quick POC or if all you are really going to do is clicking a button and do something simple that does not require any other feature. However there may be some memory save if you are having a lot of simple buttons in a screen. A benchmark comparison coming soon.
[Xamarin Docs](https://docs.microsoft.com/en-us/dotnet/api/xamarin.forms.command-1?view=xamarin-forms)

### Prism `DelegateCommand`

`DelegateCommand` is a better Command implementation because allows observing a boolean for 'CanExecute', but other than that, feels like a half-baked implementation of `ICommand`, not really intended in my opinion for use in complex apps. [Prism Docs](https://prismlibrary.com/docs/commanding.html)

### AsyncAwaitBestPractices `AsyncCommand`

`AsyncCommand` comes from package [Async Await Best Practices](https://github.com/brminnick/AsyncAwaitBestPractices) which apart from giving an implementation of ICommand with error handling, prevents the use of async void. Also the library provides for other good stuff like `SafeFireAndForget()` and `WeakEventManager` so is a handy package for Task based programming.

Unfortunately it does not provide `CanExecute` observer pattern like `DelegateCommand`, but is capable of catching exceptions if you provide an Error Handler parameter when creating the Command.

### ReactiveUI `ReactiveCommand`

From all, from what you can see in the table [ReactiveCommand](https://www.reactiveui.net/docs/handbook/commands/) is your swiss army knife implementation of `ICommand`, fully featured and rock solid, you can't go wrong with it, the flexibility of `IObservable` as consumer and implementer gives us ultimate adaptability. 

`ReactiveCommand` is also the only one capable of providing a generic typed result, additional to the default parameter in `ICommand`, to allow to retrieve the execution output, this is useful for Unit Testing because often you would want to assert the outcome of an operation starting with the click of a button end to end.

One thing that shines from the rest is also that it has built-in execution blocking so it won't allow double tap or double execution if already fired, whether is a Task or an Action. Also, you can retrieve `CanExecute` and `IsExecuting` states to have better awareness for other components that may need to know execution state.

\*While not directly capable of observing a boolean property, what RxUI Command offers is accepting the more robust `IObservable` type parameter for `CanExecute` behavior. You have to take an extra step to use `WhenAnyValue()` extension to wrap the INPC events from a property into an observable but in a real world application you rarely just watch for a single source, you could chain different observables here without having to notify of Can Execute has changed, so this is handy when having to watch multiple states at once and calculate whether or not the Command should be enabled or disabled.

In the following sections I go through a demo setup to analyze each one in deep.

## Setting up a meaningful use case 👨‍🏫

Let's say we have a minimum requirement when we click a button in our app, simple but still a realistic requirement:
- We should be able to click a button in screen to execute an Important Task
- User can control whether or not the button should be enabled
- There may be an event that would make the button not available to click, when the event for disabling it happens we disable the button, then enable it with the following event
- Button should be enabled only when the user has manually enabled it and the event for enabling it occurs.
- Oh but also the Important Task shall not be executing while another Task is happening, this is an important Task!
- Important Task may error with an Exception, handle it
- Important Task takes a parameter from the Command execution.
- After Important Task finishes we may do some operation on the result, this handler may also cause an unexpected exception, handle it but this is an unrecoverable state.

Now, let's explore our options for a minimum implementation of this, shall we?

### Defining a simple View

Here I'm using C# Markup extensions as of latest XF 4.8 (I don't think XAML is suited for UI code for reasons I'll explain in another post)

Notice I declare the Parameter and Result types to pass a parameter and return a Result from the Task to execute.

The view is simply a Button and a Switch to enable manually the the button, the command is bound to the View Model we define later here, the VM will handle results, errors and executability of the Command.

```csharp
public MainPage()
        {
            var formsVm = new FormsCmdViewModel();
            var delegateVm = new DelegateCmdViewModel();
            var asyncVm = new AsyncCmdViewModel();
            var rxVm = new ReactiveCmdViewModel();
            Content = new StackLayout
            {
                Spacing = 10,
                Children = 
                { 
                    new ContentView
                    { 
                        BindingContext = formsVm,
                        Content = new StackLayout
                        {
                            BindingContext = formsVm,
                            Children =
                            {
                                new Button { Text = "Forms Command" }
                                    .Width(50)
                                    .Height(50)
                                    .BindCommand(
                                        nameof(formsVm.FormsCommand),
                                        formsVm,
                                        parameterSource: new Parameter
                                        {
                                            Type = "Forms",
                                        }),
                                new Label { Text = "Enable Command?" },
                                new Switch()
                                    .Bind(nameof(formsVm.Enabled)),
                            },
                        },
                    },
                    new ContentView
                    { 
                        BindingContext = delegateVm,
                        Content = new StackLayout
                        {
                            BindingContext = delegateVm,
                            Children =
                            {
                                new Button { Text = "Delegate Command" }
                                    .Width(50)
                                    .Height(50)
                                    .BindCommand(
                                        nameof(delegateVm.DelegateCommand),
                                        delegateVm,
                                        parameterSource: new Parameter
                                        {
                                            Type = "DelegateCommand",
                                        }),
                                new Label { Text = "Enable Command?" },
                                new Switch()
                                    .Bind(nameof(delegateVm.Enabled)),
                            },
                        },
                    },
                    new ContentView
                    { 
                        BindingContext = asyncVm,
                        Content = new StackLayout
                        {
                            BindingContext = asyncVm,
                            Children =
                            {
                                new Button { Text = "Async Command" }
                                    .Width(50)
                                    .Height(50)
                                    .BindCommand(
                                        nameof(asyncVm.AsyncCommand),
                                        asyncVm,
                                        parameterSource: new Parameter
                                        {
                                            Type = "AsyncCommand",
                                        }),
                                new Label { Text = "Enable Command?" },
                                new Switch()
                                    .Bind(nameof(asyncVm.Enabled)),
                            },
                        },
                    },
                    new ContentView
                    { 
                        BindingContext = rxVm,
                        Content = new StackLayout
                        {
                            BindingContext = rxVm,
                            Children =
                            {
                                new Button { Text = "Reactive Command" }
                                    .Width(50)
                                    .Height(50)
                                    .BindCommand(
                                        nameof(rxVm.RxCommand),
                                        rxVm,
                                        parameterSource: new Parameter
                                        {
                                            Type = "ReactiveCommand",
                                        }),
                                new Label { Text = "Enable Command?" },
                                new Switch()
                                    .Bind(nameof(rxVm.Enabled)),
                            },
                        },
                    },
                },
            };
        }
    public class Parameter
    {
        public string Type { get; set; }
    }

    public class Result
    {
        public string Type { get; set; }
    }
```

### Declaring the Important Task

We simply define a Task with a Delay and randomly throwing an exception, a simple Result instance is returned from this.

```csharp
        private static async Task<Result> ImportantTask(Parameter parameter)
        {
            Debug.WriteLine($"Command executed from {parameter?.Type}");
            await Task.Delay(3000);
            var rnd = new Random().Next(10);
            if (rnd > 5)
            {
                Debug.WriteLine("Exception! Because it can happen");
                throw new InvalidOperationException();
            }
            return new Result{ Type = parameter?.Type };
        }
```

## Commands Implementation

Let's now explore our options to implement the Command execution and determining when is enabled or not, and also how to catch exceptions in each one.

### Option 1: Xamarin Forms `Command` 🤦‍♂️

Ok so let's firstly declare our command in the constructor of the FormsCmdViewModel:

```csharp
    public FormsCmdViewModel()
    {
        _device = new DeviceService();
        _device.StartTimer(TimeSpan.FromSeconds(3), OnEvent);
        FormsCommand = new Command<Parameter>(OnClickAsyncVoid, CanExecute);
    }
// ...
private bool OnEvent()
{
    EnabledFromEvent = !_enabledFromEvent;
    Debug.WriteLine($"Event triggered: {_enabledFromEvent}");
    return true;
}
```
Notice we use a timer to set `EnabledFromEvent` property that will be a conditional to enable the `Command` and hence, the button.

Now let's define the `OnClickAsyncVoid()` method <a name="onclickasyncvoid"></a>:
```csharp
private async void OnClickAsyncVoid(Parameter obj)
{
    // We have to await the Task and try/catch this async void,
    // otherwise we would not catch exceptions on the ImportantTask handler, 
    // like when we don't change Enabled in the Main Thread, then our app wouldn't make a noise!
    try
    {
        Enabled = false;
        try
        {
            var result = await ImportantTask(obj).ConfigureAwait(false);
            HandleResult(result);
        }
        catch (InvalidOperationException ex)
        {
            Debug.WriteLine($"Expected Exception handled! {ex}");
        }
        finally
        {
            // If you did this you would run into threading exception,
            // shows our point above.
            // Enabled = true;
            _device.BeginInvokeOnMainThread(() => Enabled = true);
        }
    }
    catch (Exception ex)
    {
        Debug.WriteLine($"Exception from handler! {ex}");
        // This is an unrecoverable state of the app!
        throw;
    }
}
```
So as you can see is a very simple method that basically does the following:
- Executes our `ImportantTask`
- Calls the result handler through `HandleResult()` method and catches the expected `InvalidOperationException`, we simply log to console these for simplicity.
- Also. We catch unexpected exceptions happening inside the execution with the outer try catch, notice that setting `Enabled = true` out of Main Thread would cause the exception, while you can remove it later after the code is safe, most of times you will want to keep a handler in cases an unexpected exception happens in more complex tasks, notice also that we crash the app as we don't know the state of the app if we ever get here!
- Lastly, it will disable the `Command` at beginning of execution and at the end setting `Enabled` property

This method completes our requirement, there is one thing we have to do so that our Button disables or enables as we operate the switch or a timed event happens, in our properties we need to call also `RaiseCanExecuteChanged()` so the `Command` evaluates `CanExecute`:

```csharp
private bool _enabled;
public bool Enabled
{
    get => _enabled;
    set
    {
        SetProperty(ref _enabled, value);
        (FormsCommand as Command)?.ChangeCanExecute();
    }
}

private bool _enabledFromEvent;

private bool EnabledFromEvent
{
    get => _enabledFromEvent;
    set
    {
        SetProperty(ref _enabledFromEvent, value);
        (FormsCommand as Command)?.ChangeCanExecute();
    }
}
```

This method will be also used for `DelegateCommand`, for the `CanExecute()` method we simply define that both booleans should be true:
```csharp
private bool CanExecute(Parameter obj)
{
    return Enabled && EnabledFromEvent;
}
```

### Option 2: Prism `DelegateCommand` 💆‍♂️

Well, I was thinking that 
```csharp
ObservesCanExecute(Func<bool> canExecute);
```
would accept the 2 conditions we have set up at once, but it will not, so only you can observe properties with `ObservesProperty()`, however you can chain together several so in this case we would not need to call `RaiseCanExecuteChanged()` which is analogue to XF Command's `ChangeCanExecute()` like this:

```csharp
DelegateCommand = new DelegateCommand<Parameter>(OnForms, CanExecute)
    .ObservesProperty(() => Enabled)
    .ObservesProperty(() => EnabledFromEvent);
```

Here, `ObservesProperty()` method, allows us to save some code delegating the knowledge of when to call `RaiseCanExecuteChanged` automatically, to the Command itself, instead of imperatively calling it in the properties! We sort of pull the state, not push it, which is one essential aspect of *Reactive paradigm*, but this is not using *Reactive Extensions* at all. Notice that this will tell when to call `CanExecute()`, not really evaluating the properties altogether, so you can still have arbitrary logic in the `CanExecute()` method.

and that's it... the `OnClickAsyncVoid` [defined before](#onclickasyncvoid) is exactly the same, let's move on!

### Option 3: `AsyncCommand` 🧰

The most interesting use of `AsyncCommand` is that it can handle passing Tasks for execution and a way to handling errors out of the box, that way we have the following declaration:

```csharp
AsyncCommand = new AsyncCommand<Parameter>(
    OnClickAsyncTask,
    CanExecute,
    OnError);
```
This allows to convert our `OnClickAsyncVoid()` to an `OnClickAsyncTask()` <a name="onclickasynctask"></a> to be simplified a bit:

```csharp
        private async Task OnClickAsyncTask(Parameter obj)
        {
            Enabled = false;
            try
            {
                // Ideally, we would return the Task instead of awaiting here,
                // but we would not be able to retrieve the Result at Command level
                var result = await ImportantTask(obj).ConfigureAwait(false);
                HandleResult(result);
            }
            catch (InvalidOperationException ex)
            {
                Debug.WriteLine($"Expected Exception handled! {ex}");
            }
            finally
            {
                // If you did this you would run into threading exception,
                // shows our point above.
                // Enabled = true;
                _device.BeginInvokeOnMainThread(() => Enabled = true);
            }
        }
```
This will remove some code from the method and remove the async void!

However, we have to still call explicitly when we want it to evaluate the conditions for `CanExecute` behavior contrary to `DelegateCommand`:

```csharp
(AsyncCommand as AsyncCommand<Parameter>)?.RaiseCanExecuteChanged();
```

And also explicitly enable and disable the button as all previous examples. But this can be done better!

### Option 4: `ReactiveCommand` 👨‍🔬

Let's declare our `ReactiveCommand` functionality as follows:

```csharp
RxCommand = ReactiveCommand
    .CreateFromTask<Parameter, Result>(
        ImportantTask,
        CanExecute());
RxCommand
    .Subscribe(HandleResult);
RxCommand
    .ThrownExceptions
    .Subscribe(OnError);
```

A lot is going on here! So let's demystify it. The first declaration is similar to others, we use the static `CreateFromTask()` method to pass in this case not the `OnClickAsyncTask` anymore, but the `ImportantTask` directly. 

This saves us a lot of code because as you may remember, this command can take a Task but also the Command enables and disables when the Task starts and completes, respectively.

Also, we don't need to wrap the Task calling into an `async` method because we can simply `Subscribe()` to the execution completion of the `ReactiveCommand`, which allows to retrieve the result and pass it to our `HandleResult` method or do something else as the command is an `IObservable<T>` itself.

Lastly, `ReactiveCommand` provides a way to catch any thrown Exceptions through `ThrownExceptions` observable. We pass the `OnError` handler but as we don't have a way to filter through the exceptions, we simply type sniff the exception as follows:

```csharp
private void OnError(Exception ex)
{
    if (ex is InvalidOperationException)
    {
        Debug.WriteLine($"Expected Exception handled! {ex}");
    }
    else
    {
        Debug.WriteLine($"Exception from handler! {ex}");
        // This is an unrecoverable state of the app!
        RxApp.DefaultExceptionHandler.OnNext(ex);
    }
}
```

This may not be ideal for more complex scenarios, in which case we can still keep a very slim version of [`OnClickAsyncTask()`](#onclickasynctask) while also keeping the unexpected exception handler:

```csharp
private async Task<Result> OnClickAsyncTask(Parameter obj)
{
    try
    {
        return await ImportantTask(obj).ConfigureAwait(false);
    }
    catch (InvalidOperationException ex)
    {
        Debug.WriteLine($"Expected Exception handled! {ex}");
        return default;
    }
}
```
We now don't have the side effects as in the previous method version, notice that even if is an async Task, it is a generic `Task<TResult>` which the `ReactiveCommand` can easily make available to us, something you simply can't do with any other Command, that however comes with a bit of a price, `ICommand` is still an interface `ReactiveCommand` implements but to handle result operations it also implements `IObservable<TResult>`, so you will need to declare the command property differently:

```csharp
public ReactiveCommand<Parameter, Result> RxCommand { get;}
```

All in all, this has allowed us to have a *Single Responsibility* method, such as execute our Task and handle any errors coming from it, no need to care about the execution state of the Command or if there is another error down the road of execution that we can't handle. 

Lastly, let's explore the `CanExecute` part, in order to mimic what DelegateCommand's `ObservesProperty()` can do we have to pass an `IObservable<bool>` to the command declaration, so we have to modify `CanExecute()` as follows:

```csharp
private IObservable<bool> CanExecute()
{
    return this.WhenAnyValue(
        vm => vm.Enabled,
        vm => vm.EnabledFromEvent,
        (enabled, enabledEvent) => enabled && enabledEvent);
}
```
We use the `WhenAnyValue` extension method from *ReactiveUI* to observe the INPC events easily and at once for both properties `Enabled` and `EnabledFromEvent`, the third argument is a selector, so you can pass a custom logic to evaluate the two properties observed, in this case we simply want both to be true, but again, this is a powerful tool to enable complex logic as you can see.

Note also, that even though we had to make this method return `IObsevable<bool>`, it is now in a whole different league than just observing boolean properties, meaning you can chain other observables together to create complex pipelines. Plus we don't need to tell the command to evaluate imperatively this condition on each property setter, as it should be!

Again, we don't need to tell the Command when it should enable through the properties, a function is responsible to evaluate it when something changes, we react.

### Bonus code! 🎁

You may notice that for simple cases like ours, the `IObservable<bool>` for `CanExecute` parameter may be a bit hard to read specially since you are only evaluating 2 booleans. So what I did is try to mimic the way `DelegateCommand` is able to observe properties with `ObservesCanExecute()` in a compact way.

While I'm a total newbie dealing with [C# Expressions](https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/expression-trees/), I was able to come up with a quick and dirty extension method that will create our `IObservable<bool>` for us, given 1 or 2 INPC enabled boolean properties. I give you 'WhenAnyValueMixin' class:

```csharp
public static class WhenAnyValueMixin
{
    public static IObservable<bool> ObservesProperty<TSource>(
        this TSource target,
        Expression<Func<bool>> property1)
    {
        return target.WhenAnyValue(
            GetExpression<TSource>(property1));
    }
    
    public static IObservable<bool> ObservesProperty<TSource>(
        this TSource target,
        Expression<Func<bool>> property1,
        Expression<Func<bool>> property2)
    {
        return target.WhenAnyValue( 
            GetExpression<TSource>(property1),
            GetExpression<TSource>(property2), 
            (p1, p2) => p1 && p2);
    }

    private static Expression<Func<TSource, bool>> GetExpression<TSource>(
        Expression<Func<bool>> property1)
    {
        // This expression is our goal for the ObservableForProperty():
        // Expression<Func<ReactiveCmdViewModel, bool>> target;
        // And this parameter is a MemberExpression (=> Enabled) (because is a member?)
        if (!(property1.Body is MemberExpression exp)) 
        {    
            // Let user know if is not MemberExpression
            throw new NotSupportedException("MemberExpression expected!");
        }

        // Expression for the Parameter type we need in the goal above, assuming we have a member on TSource.
        var parameter = Expression.Parameter(typeof(TSource));
        // Create Member Access Expression, as in vm => vm.Enabled from the Member Info from the above of course.
        var memberAccess = Expression.MakeMemberAccess(parameter, exp.GetMemberInfo());
        // Create target expression from the member access and parameter expressions so we get vm => vm.Enabled to get it's observable below
        var lambda = Expression.Lambda<Func<TSource, bool>>(memberAccess, parameter);

        return lambda;
        // Fpr reference, started with this
        // return this.ObservableForProperty(lambda,  false, false)
        //     .Select((change, i) => change.Value);
    }
}
```

As this is kind of out of scope for this post, I'll leave it to you to explore the code, which is not much, but this allows to declare our `CanExecute()` this way!

```csharp
private IObservable<bool> CanExecute()
{
    // Mimicking DelegateCommand with WhenAnyValue here:
    return this.ObservesProperty(
        () => Enabled,
        () => EnabledFromEvent);
}
```

Notice also you only need to pass `CanExecute()` to the Command, not the ObservesProperty in the Command declaration which is required for DelegateCommand, this is doing both evaluating CanExecute and Observing the properties for both being true in a single shot. Also, you can still attach a selector so you can do arbitrary logic on the 'ticked' values from the Observable.

Pretty neat!

## A winner? 🏆

I have made up my mind, after trying out all of them now, to me there is not better implementation of `ICommand` + `IObservable` than Reactive UI, in my opinion we don't need any other implementation.

Consider also how much we reduced our code footprint in each iteration!

Factor | XF Command | DelegateCommand | AsyncCommand | ReactiveCommand
------------------- | --------- | --- | --- | ---
Enabled/EnabledFromEvent property setters lines | 4 | 2 | 4 | 2 
OnClickAsyncVoid/OnClickAsyncTask executors lines | 25 | 25 | 17 | 0-12 
OnClick* cognitive complexity | 2 | 2 | 1 | 0-1
Readability weight (1-5) | 1 | 3 | 2 | 4 

The last one may be subjective but I think the `ReactiveCommand` version of the ViewModel is more readable, with less side effects and more scalable. This comes more evident as your complexity increases and you realize reactive programming is a natural fit for some advanced scenarios. Again, all this was all a simple example but is a good starting point for Reactive Extensions and ReactiveUI, one command to rule them all 😁

I find it unfortunate that the Reactive Paradigm is just gaining momentum even though has more than a decade of existence, and that's why few frameworks are leveraging Reactive Extensions, using Rx super charges a tool and makes it more versatile to use; [Shiny](https://github.com/shinyorg/shiny) is a good example of providing the flexibility of Reactive in a library and hope that's a trend.

I also have started a project that tries to close the gap on examples (still being cooked!) using Reactive and also be useful as an Architecture guidance, [CleanRx](https://github.com/keozx/CleanRx)