redux-net-un-contendor-de-estado-para-aplicaciones-net

Redux.NET, un contendor de estado para aplicaciones .NET

Redux.NET es un contenedor de estado predecible para aplicaciones .NET basado en el desarrollo Redux para JS https://github.com/reactjs/redux.

Redux es una popular librería Open Source para JavaScript https://github.com/reactjs/redux, que ha inspirado a muchos otros frameworks como Vuex para VueJs.

Redux.NET traslada la filosofía de estos contenedores de estado cuyo propósito es abstraer el estado de una aplicación, de forma que sea compartido de forma sencilla por todos los componentes de una aplicación.

Cuando desarrollamos una aplicación en MVVM una de las primeras preocupaciones normales es como intercambiar información entre los componentes de una aplicación, manteniendo débil el acoplamiento entre clases.

Así, tenemos varias opciones disponibles habitualmente, entre las que se incluyen el patrón emisor-suscriptor (Messenger), la inversión de contenido (IoC) y la inyección de dependencias.

Redux.NET es una alternativa o complemento a estas metodologías. Según la filosofía Redux, el contenedor de estado es “predecible” dado que cumple 3 condiciones.

  • El estado es único para toda la aplicación
  • El estado es de sólo lectura
  • El cambio de un estado a otro se realiza a través de acciones

Para conseguir esto el funcionamiento de Redux.NET (al igual que el de Redux) se basa en tres componentes,

  • Store, almacena el estado de la aplicación en un objeto T
  • Actions, son llamadas por nuestros objetos para realizar acciones en la Store./li>
  • Reducers, definen las transiciones entre un estado y otro al recibir una acción

La librería proporciona varios ejemplos para ilustrar su uso. Vamos a explicar las partes más importantes del más sencillo de ellos, el ejemplo ‘Counter’ que contiene simplemente un contador que incrementa o decrementa su valor.

En primer lugar, en la clase App hemos definido una IStoredado que en este sencillo ejemplo la única variable que identifica el estado de la aplicación es el valor del contador.

public sealed partial class App : Application
{
  public static IStore<int> CounterStore { get; private set; }

  public App()
  {
    InitializeComponent();
    
    CounterStore = new Store<int>(CounterReducer.Execute, 0);
  }

  protected override void OnLaunched(LaunchActivatedEventArgs e)
  {
    // omitted for example
  }
}

Por otro lado, hemos definido en un archivo las acciones que admite nuestra Store, y que serán lanzadas desde el ViewModel.

public class IncrementAction : IAction { }

public class DecrementAction : IAction { }

También se define el Reducer necesario, que define el siguiente estado en función del estado actual y la acción recibida. En este ejemplo, simplemente el nuevo estado es incrementar/decrementar la variable, respectivamente.

public static class CounterReducer
{
  public static int Execute(int previousState, IAction action)
  {
    if(action is IncrementAction)
    {
      return previousState + 1;
    }

    if(action is DecrementAction)
    {
      return previousState - 1;
    }

    return previousState;
  }
}

Con todo esto definido, ahora veremos cómo llamarlo desde el ViewModel (en este caso desde el UI, porque el ejemplo proporcionado es muy simple).

Como vemos, los botones de Increment y Decrement emplean la Store, a la que envían las acciones definidas previamente.

Por otro lado, en el constructor, nos suscribimos a los cambios de estado. En este ejemplo, simplemente se actualiza el valor del contador al nuevo estado.

public sealed partial class MainPage : Page
{
  public MainPage()
  {
    this.InitializeComponent();

    App.CounterStore.Subscribe(counter => CounterRun.Text = counter.ToString());
  }

  private void IncrementButton_Click(object sender, Windows.UI.Xaml.RoutedEventArgs e)
  {
    App.CounterStore.Dispatch(new IncrementAction());
  }

  private void DecrementButton_Click(object sender, Windows.UI.Xaml.RoutedEventArgs e)
  {
    App.CounterStore.Dispatch(new DecrementAction());
  }
}

Es un ejemplo muy sencillo pero que permite introducir los tres elementos fundamentales (Store, Actions, y Reducers). Es sencillo extrapolar este ejemplo a un proyecto real, donde la Store tendría un objeto más complejo que contendría las variables necesarias para representar el estado de la aplicación.

Desde luego, Redux.NET es una librería interesante, aunque requiere un cambio tanto de mentalidad como de arquitectura. Podríamos discutir incluso si presenta un patrón o anti-patrón ya que, en cierta forma, es llevar al extremo el patrón singleton o las (a menudo) odiadas variables estáticas.

En cualquier caso, merece la pena echarle un ojo. Las librerías como Redux o Vuex son una tendencia en el desarrollo Web y es así, porque son útiles y permiten la reutilización e independencia entre componentes. Además, encajan perfectamente en con el uso de IoC.