Arquitectura QuickFlux para QtQuick (QML): Flujo Unidireccional de Datos

Introducción a los Principios de Flujo Unidireccional

El patrón de arquitectura Flux, popularizado por Facebook, promueve un flujo de datos predecible y de una sola dirección en las aplicaciones. Esto contrasta con los patrones MVC tradicionales. La idea central es que los datos "fluyen" en una sola dirección a través de la aplicación: desde las acciones que los desencadenan, a través de un punto central de distribución, hacia los contenedores de estado, y finalmente hacia la interfaz de usuario que los presenta.

QuickFlux es una implementación específica de este patrón para el ecosistema de QtQuick (QML). Su objetivo principal es desacoplar la lógica de la interfaz de usuario del estado de la aplicación, haciendo que el manejo de eventos y la actualización de la UI sean más rastreables y fáciles de mantener.

Componentes Clave del Flujo

Un flujo típico se compone de varias piezas que trabajan en conjunto. La interacción del usuario en la Interfaz (View) genera una Acción (Action). Esta acción es enviada a un Despachador (Dispatcher) central. El despachador entonces notifica a todos los Almacenes (Stores) registrados. Cada almacén evalúa la acción, actualiza su propio estado interno si corresponde, y notifica a la interfaz de los cambios, que se re-renderiza con los nuevos datos.

Este modelo garantiza que la fuente de la verdad (el estado) resida en los almacenes, que son los únicos que pueden modificarla. La interfaz de usuario es, en esencia, una vista de solo lectura derivada de ese estado.

Visualización del Proceso

El diagrama siguiente ilustra esta secuencia de comunicación unidireccional:

Un proyecto que implementa QuickFlux típicamente sigue una estructura de directorios que refleja esta separación de responsabilidades:

/mi_proyecto
├── /acciones
│   ├── TiposAccion.qml
│   └── AccionesApp.qml
├── /almacenes
│   ├── AlmacenRaiz.qml
│   └── AlmacenPrincipal.qml
├── /vistas
│   └── ...
└── main.qml

Definición de Tipos de Acción y Acciones

El archivo TiposAccion.qml actúa como un catálogo de constantes (o cadenas de texto) que identifican de manera única cada tipo de acción posible en la aplicación. Esto centraliza la definición y evita errores tipográficos.

pragma Singleton
import QtQuick 2.0

QtObject {
    readonly property string iniciarSesion: "APP/INICIAR_SESION"
    readonly property string eliminarElemento: "APP/ELIMINAR_ELEMENTO"
}

AccionesApp.qml es el copmonente que realmente crea y dispara las instancias de acciones hacia el despachador. Las vistas o lógica de alto nivel invocan métodos aquí.

pragma Singleton
import QtQuick 2.0
import QuickFlux 1.1

ActionCreator {
    function iniciarSesion(credenciales) {
        dispatch(TiposAccion.iniciarSesion, {usuario: credenciales.usuario});
    }

    function solicitarEliminacion(idItem) {
        dispatch(TiposAccion.eliminarElemento, {id: idItem});
    }
}

Almacenes de Estado (Stores)

Los almacenes contienen el estado de la aplicación y la lógica para procesar las acciones recibidas. El AlmacenRaiz.qml se encarga de vincular el almacén al despachador de la aplicación.

pragma Singleton
import QtQuick 2.0
import QuickFlux 1.1

RootStore {
    // Vincular el origen de acciones al despachador global
    bindSource: AppDispatcher

    // Propiedades que representan el estado
    property bool usuarioAutenticado: false
    property var elementos: []

    // Escuchar acciones específicas
    Filter {
        type: TiposAccion.iniciarSesion
        onDispatched: {
            // Lógica para actualizar el estado
            usuarioAutenticado = true;
        }
    }

    Filter {
        type: TiposAccion.eliminarElemento
        onDispatched: {
            var idAEliminar = message.id;
            elementos = elementos.filter(function(el) {
                return el.id !== idAEliminar;
            });
        }
    }
}

Los componentes de la interfaz de usuario (vistas/) enlazan sus propiedades a las del almacén. Cuando cambia el estado en el almacén, la vista se actualiza automáticamente gracias al sistema de bindings de QML.

import QtQuick 2.12
import QtQuick.Controls 2.5

ListView {
    model: AlmacenPrincipal.elementos
    delegate: Text {
        text: modelData.nombre
    }
}

Etiquetas: QtQuick QML Flux Arquitectura de aplicaciones Estado de la interfaz de usuario

Publicado el 6-5 01:16