Rendering e mantenimento delle modifiche dello stato in un'app Web con programmazione funzionale

2

Supponiamo che tu abbia un'app tic-tac-toe.

  • C'è lo stato del gioco che può essere rappresentato da un array di dimensioni 9.
  • C'è il tuo "riduttore" che calcola il nuovo stato dal vecchio stato e dalle azioni del giocatore.
  • Poi c'è il tuo renderer che aggiorna l'interfaccia utente in base al nuovo stato.

Grande! Nozioni di base sulla programmazione funzionale. Sfortunatamente, qui finisce la maggior parte delle risorse online. Parlano tutti di come scrivere la logica in modo puro, senza effetti collaterali, non mutando dati o riassegnando valori. Quello su cui non si espandono molto è quello che succede dopo:

  1. In che modo viene mantenuto il nuovo stato dall'app?

    Se contrassegno una cella sulla lavagna "X", l'app prende la mia mossa, calcola il nuovo stato, rende nuovamente la griglia. Ma non posso modificare l'array originale, né posso assegnarlo alla stessa variabile. In che modo l'app mantiene il nuovo stato?

  2. In che modo il rendering può essere puro in un'app Web?

    Se contrassegno una cella sulla lavagna "X", l'app prende la mia mossa, calcola il nuovo stato, rende nuovamente la griglia. Ma per ri-renderizzare la griglia, starei manipolando il DOM, che sta effettivamente mutando una struttura dati. Come si aggiorna il DOM funzionalmente?

Vengo da uno sfondo di sviluppo web, dove di solito si tratta di aspettare eventi, di modificare i dati e manipolare DOM, raramente in vista di FP. Inoltre, la maggior parte parla di mantenere lo stato nello stack, solitamente in una forma di ricorsione, che non è una cosa nelle app web. Quindi sto attraversando un periodo difficile per comprendere il concetto, specialmente quando i materiali descrivono modelli che non sono applicabili. Suggerimenti per la giusta direzione è apprezzato.

    
posta Joseph 21.03.2018 - 03:25
fonte

1 risposta

3

La programmazione funzionale comprende una vasta gamma di tecniche. Immutabilità e purezza sono concetti importanti perché consentono un ragionamento equo , ma il loro utilizzo è spesso scomodo. In effetti, la maggior parte della programmazione funzionale diversa da Haskell non supporta uno stile di programmazione completamente puro e immutabile. Invece, Scheme, OCaml o JavaScript sono lingue imperative funzionali in cui lo stato di muting è normale.

Se guardiamo a diversi modi di fare programmazione funzionale, l'attenzione non sembra essere immutabilità o ragionamento equo, ma che usiamo tecniche come funzioni di prima classe, chiusure e algoritmi ricorsivi. Se stai usando JS, probabilmente hai già utilizzato un sacco di tecniche funzionali!

Invece di sbarazzarsi dello stato, spesso è già abbastanza utile rendere esplicito tutto lo stato. Per esempio. invece di un metodo che aggiorna un oggetto di stato del gioco, fare in modo che il metodo restituisca uno stato di gioco nuovo . È ancora perfettamente bene riassegnare le tue variabili. Non sarebbe inusuale vedere qualcosa di simile ai confini del tuo sistema:

var state = GameState(initial);
userInterface.onInteraction(function updateState(e) {
  state = calculateNewState(state, e);
  userInterface.drawState(state);
});
userInterface.drawState(state);

In teoria questo potrebbe essere cambiato per usare la ricorsione invece di una variabile mutabile, ma se i due approcci sono funzionalmente equivalenti allora ha senso usare l'approccio più leggibile, sia che sia più "puro" o meno. Con la stessa argomentazione, è ancora perfettamente appropriato utilizzare foreach-loops nel codice funzionale, anche se hanno senso solo con la programmazione imperativa. Ma questo è il nocciolo della questione:

Lo stato non è male. Lo stato mutabile condiviso rende un programma più complesso e la complessità è rischiosa. Lo stato mutabile locale (ad esempio una variabile che viene riassegnata) è totalmente soddisfacente, anche in FP.

In un'app Web, il DOM è discutibilmente stato mutabile perché è globale. Questo non significa che non puoi usare FP, questo significa che ha senso isolare la tua logica da questo stato. Nel tuo caso particolare, ha senso che il DOM non sia mai il modello di dati canonico della tua applicazione. Invece, il DOM potrebbe essere ridisegnato dallo stato attuale del gioco. Il DOM non conterrebbe quindi alcun stato significativo dal punto di vista della tua app, in quanto si tratta solo di un target di output.

    
risposta data 22.03.2018 - 23:46
fonte

Leggi altre domande sui tag