Nel film Interstellar, c'è una scena angosciante in cui i protagonisti scendono sul pianeta di Miller. A causa dell'estrema gravità del buco nero vicino, subiscono una brutale dilatazione temporale: un'ora passata su quel pianeta equivale a 7 anni sulla Terra.
Ogni volta che vedo quella scena, penso ai miei utenti quando cliccano "Salva" su una mia applicazione web mal ottimizzata.
La percezione del tempo non è assoluta, né in astrofisica né in UI/UX Design. Per un server backend, elaborare una richiesta al database in 800 millisecondi è un trionfo di efficienza. Ma per un essere umano che fissa uno schermo congelato aspettando che un bottone cambi colore, 800 millisecondi sono un'eternità frustrante.
Il Fango: L'Attesa Bloccante
Nel mio primo vero progetto freelance (un gestionale per un magazzino), dovevo implementare il pulsante "Metti nei Preferiti".
Seguendo alla lettera i tutorial di base, ho implementato il flusso classico: l'utente clicca, mostro un loader, aspetto la risposta del server, se va bene aggiorno l'interfaccia.
// Bad Code: Sottomettere l'utente alla dilatazione temporale
async function handleLikeRushed() {
setLoading(true); // Blocco l'interfaccia. Inizia l'ansia.
try {
// Il server è in America, il database è lento. Passa 1 secondo.
await api.post('/like', { itemId });
setIsLiked(true); // Finalmente, dopo "7 anni", l'icona si colora.
} catch (e) {
showError();
} finally {
setLoading(false);
}
}
Cosa facevano gli utenti del magazzino? Cliccavano. Vedevano la rotellina girare. Si infastidivano per la latenza, pensavano che non avesse preso il click, e cliccavano di nuovo. Inviavano cinque richieste identiche al backend prima ancora che la prima fosse risolta, mandando in tilt il database.
L'Ingegneria: Optimistic UI
L'ingegneria moderna del frontend ha inventato una soluzione per "ingannare" questa dilatazione temporale: la Optimistic UI.
Il trucco è semplice ma psicologicamente devastante: assumi (ottimisticamente) che il server dirà di sì, e aggiorni l'interfaccia immediatamente. L'azione sembra istantanea. Nel frattempo, in background (nello spazio profondo), la richiesta viaggia verso il server. Se miracolosamente dovesse fallire, farai un "rollback" annullando l'azione.
// Good Code: Aggiornamento Ottimistico
async function handleLikeEngineering() {
// 1. Salvo lo stato precedente in caso di disastro
const previousState = isLiked;
// 2. Inganno il tempo: aggiorno IMMEDIATAMENTE la UI.
// L'utente percepisce zero latenza. È felice.
setIsLiked(!isLiked);
try {
// 3. Comunico col buco nero (il backend) in modo silenzioso
await api.post('/like', { itemId, like: !isLiked });
} catch (error) {
// 4. Rollback: se l'universo ci rema contro, ripristino il passato.
setIsLiked(previousState);
toast.error("Ops, salvataggio fallito.");
}
}
Il Takeaway
Il tempo è relativo. Una latenza di mezzo secondo è invisibile nei log di sistema, ma è uno scoglio enorme per l'esperienza utente.
Quando progettate un'interfaccia, smettetela di tenere i vostri utenti in ostaggio sul pianeta di Miller. Applicate l'Optimistic UI alle azioni reversibili (come i like, le spunte, i toggle). Date l'illusione di una velocità sovrumana; lasciate che sia il codice asincrono sotto il cofano a fare i conti con i buchi neri della rete.