Unidirectional Data Flow

Un camino explícito para cambiar estado y presentación

Unidirectional Data Flow (UDF) organiza cambios de estado de UI o aplicación mediante un camino dirigido: una entrada o intención llega a lógica de transición, produce estado observable y permite actualizar la representación. Evita depender de que pares arbitrarios se modifiquen mutuamente para completar una interacción. Esta es una definición amplia de trabajo del Atlas, no una implementación universal.

La dirección describe cómo se propagan cambios dentro del alcance elegido. No exige que el usuario envíe un único mensaje: ve un resultado, vuelve a interactuar e inicia otro ciclo. Ese feedback humano no vuelve bidireccional el camino interno de actualización. Tampoco elimina consultas, notificaciones o colaboración entre elementos; pide explicar sus papeles.

Interacción → intención → transición → estado observable → UI
                            ↑
Resultado de un efecto → nueva entrada

El esquema es síntesis del Atlas. No declara clases obligatorias, una función matemática única ni dependencia de código. dependency-structure examina qué conoce cada unidad; communication examina intercambios. UDF no es una topología de red ni un mandato de imports en una sola dirección.

Ownership, entradas y transición

Para una interacción concreta conviene poder responder quién conserva el estado, quién puede solicitar cambios, quién realiza la transición y quién observa el resultado. Puede haber responsables por pantalla, feature o componente; no hace falta un único owner global. El alcance evita que dos copias editables compitan silenciosamente por representar el mismo resultado.

El input puede llamarse action, event, message o intent según el ecosistema. No asumir que toda realización usa actions ni que esos valores representan hechos persistidos. Una intención de guardar solicita trabajo; una respuesta recibida informa lo observado. Nombrarlas con claridad permite entender qué transición se espera sin conocer el gesto físico que la originó.

La transición calcula o produce el siguiente estado relevante. Puede utilizar funciones puras o actualizar estado mutable bajo responsabilidad delimitada, según la arquitectura. Un pure reducer es una realización específica, no la definición general. También conviene distinguir transición lógica de render inmediato: una plataforma puede agrupar actualizaciones o programar su representación después.

La UI suele derivar su representación del estado actual, sin que cada pixel deba almacenarse centralmente. Un menú abierto, un borrador o una animación pueden conservar estado local o efímero; otros detalles pertenecen a la plataforma. client-state-management desarrolla ownership, alcance y lifecycle: aquí importa no convertir UDF en centralización obligatoria.

Efectos y resultados que vuelven al flujo

Peticiones de red, storage, timers, analytics, navegación y APIs del dispositivo tienen efectos externos al cálculo de la representación. Un diseño necesita identificar dónde se ejecutan, quién inicia el trabajo y cómo regresan éxito, rechazo o fallo. La dirección del flujo no prescribe middleware, comandos de una biblioteca o un único coordinador de efectos.

En Save, la intención puede marcar una operación pendiente y provocar una petición. Su resultado se transforma en otra entrada; una transición decide cómo actualizar lo visible. Un efecto que modifica controles y otras copias del estado por caminos ocultos puede deshacer la trazabilidad buscada, aunque exista un store con un nombre conocido.

Dirección y tiempo son decisiones diferentes. Editar un texto puede producir una transición local inmediata; guardar puede requerir espera asíncrona. UDF no exige async, ni procesar todo en un hilo separado. También necesita especificar qué ocurre cuando un efecto termina después de abandonar la pantalla o cambiar de entidad.

Una respuesta tardía no debería aplicarse indiscriminadamente al contexto actual. Identidad de operación, orden, lifecycle y reglas para aceptar resultados siguen siendo preguntas de diseño. Cancelar una espera local tampoco demuestra cancelar un efecto remoto. Conservar esas incertidumbres evita atribuir a la forma del flujo garantías que pertenecen a contratos y coordinación.

Flux, Redux y Elm: ejemplos con vocabulario propio

El material original de Flux describe Actions, Dispatcher, Stores y Views. Los stores mantienen estado y lógica, reciben actions mediante callbacks registrados y notifican cambios a vistas interesadas. Su contraste con MVC responde al problema que sus autores discutían; no demuestra que toda variante de MVC impida actualizaciones dirigidas. El proyecto está archivado y se usa aquí como fuente conceptual histórica.

Redux Fundamentals explica un store para estado global, actions y cambios mediante reducers puros con actualizaciones inmutables. Estas reglas pertenecen a Redux: UDF no requiere Redux, single store, inmutabilidad total ni programación funcional. Reducers de Redux no contienen efectos; su documentación de efectos distingue lógica externa y mecanismos como middleware. No se extrapola ese mecanismo a toda UI.

The Elm Architecture organiza Model, Update y View: estado, evolución basada en mensajes y representación. La guía incorpora commands y subscriptions para interactuar con el exterior. No es Flux con otros nombres ni exige que otro lenguaje reproduzca su runtime. Estos tres ejemplos materializan flujo dirigido con estructuras diferentes.

RealizaciónEstado e inputTransición y representaciónEfectos
Flux originalStores; Actions vía Dispatcher.Stores procesan y notifican; Views consultan.Resultados externos pueden originar Actions.
ReduxEstado del store; Actions despachadas.Reducers; UI observa el estado.Fuera de reducers; mecanismos documentados por Redux.
Elm ArchitectureModel; Messages.Update y View.Commands y subscriptions gestionados con el runtime.

La tabla compara papeles, no equivalencias exactas ni ratings. La guía Android de UI ofrece otro contexto: state holders, estado hacia UI y eventos hacia su responsable. Allí UDF se denomina architecture pattern y suele colaborar con ViewModel. La clasificación editorial concept del Atlas conserva el fenómeno general, no impone una taxonomía única a estas fuentes.

Relación con MVC, MVP y MVVM

presentation-patterns organiza reparto de responsabilidades; UDF interroga propagación de cambios. Son dimensiones relacionadas que pueden combinarse. model-view-controller tiene variantes históricas y Web con colaboraciones diferentes. Una interpretación de MVC puede organizar transiciones dirigidas; no basta su nombre para deducir un grafo de cambios inevitablemente circular.

Un Presenter puede recibir intención, coordinar una operación y actualizar representación de manera explícita. Passive View y Supervising Controller distribuyen sincronización de modo diferente. Esa organización no se convierte automáticamente en Flux ni exige cambiar el nombre del patrón para reconocer una propiedad del flujo.

model-view-viewmodel puede consumir eventos y exponer estado para bindings. MVVM no implica universalmente mutación bidireccional: hay one-way, two-way y otros mecanismos según plataforma. Two-way binding puede reducir coordinación explícita para edición; en interacciones complejas puede dificultar seguir origen y propagación. Su costo depende del alcance, no es un error inherente.

El formulario Edit Customer permite comparar sin cambiar el problema. DraftName, validación, saving y error son estados pertinentes. Editar produce una entrada; validar modifica feedback; Save captura el borrador que envía; la respuesta actualiza estado confirmado o conserva texto rechazado. MVC, MVP o MVVM pueden distribuir esas responsabilidades con mecanismos distintos.

Commerce: PayRequested no equivale a pago confirmado

En este ejemplo propio, el cliente de checkout muestra resumen, disponibilidad de Pay y estado de operación. La interacción produce PayRequested; una transición registra submitting y un efecto solicita la operación al backend. Respuesta o fallo originan nuevas entradas que permiten mostrar confirmación, rechazo o incertidumbre, según el contrato real.

El browser posee estado de presentación, no autoridad automática sobre pagos. data-ownership conserva la diferencia: una copia de PaymentStatus puede estar desactualizada y Payments sigue gobernando el estado comercial. Deshabilitar el botón ayuda a coordinar interacción local, pero no prueba que no existan solicitudes duplicadas desde otros canales o tras un reinicio.

Si llega timeout, cambiar la UI a «pago fallido» podría afirmar algo que no se sabe. El flujo dirigido permite localizar dónde se tomó esa decisión; no la vuelve correcta. Si dos intentos se superponen, hacen falta políticas para interpretar respuestas tardías y resultado autoritativo, no solo un reducer más grande.

La página puede haber recibido HTML del servidor e incorporar después este ciclo. rendering-strategies decide dónde y cuándo se produjo esa representación; UDF organiza cambios posteriores. Mostrar esa composición evita confundir un store o una biblioteca cliente con la estrategia de entrega de todo Commerce.

Beneficios, costos y límites

Restringir rutas de actualización puede facilitar trazabilidad, explicación de ownership y pruebas de transiciones. No garantiza software simple: un store enorme, inputs ambiguos o una red de efectos pueden seguir siendo difíciles de comprender. testability necesita también comprobar UI real, bindings, red y comportamiento de plataforma; tests aislados no cubren esa integración.

Datos inmutables pueden ayudar a observar cambios y conservar snapshots, pero son una decisión adicional fuera de las reglas particulares de cada implementación. Algunas realizaciones permiten replay o time-travel debugging si los cambios son reproducibles. Repetir estado de UI no revierte efectos externos ni demuestra que una petición pueda repetirse con seguridad.

UDF no equivale a Event Sourcing: organizar cambios visibles no exige persistir un historial como fuente del estado. Tampoco es automáticamente CQRS por separar intención de cambio y lectura para rendering. Esos nombres tienen alcances propios; aquí no se crean nuevos canónicos ni se utiliza su prestigio para ampliar la definición.

El costo puede incluir ceremonia, indirection, traducciones, estado duplicado, sincronización derivada y coordinación de efectos. Para una interacción trivial quizá exceda el beneficio; para una colaboración rica puede hacer explícitas rutas antes implícitas. trade-off-analysis ayuda a relacionar esos costos con necesidades, evitando recomendar global stores para cualquier pantalla.

Preguntas para reconocer una realización

Seguir una interacción de principio a fin: input, owner, transición, efecto, resultado y representación. Comprobar qué puede cambiar el estado por fuera del camino declarado y por qué; revisar solapamiento, error y abandono de pantalla. El criterio no es encontrar carpetas Actions/Reducers ni afirmar que un framework «es UDF».

One-way data flow, UDF, update loop y state-management architecture aparecen en fuentes con énfasis diferentes. No se atribuye un origen histórico único al concepto ni se mezclan Flux, Redux y Elm en una arquitectura ficticia. frontend-and-client-architecture conserva esas fronteras; client-state-management examina qué estado participa y cómo se mantiene, sin absorber la pregunta por el flujo de cambios.