Qual è lo schema di progettazione "Correggi tutto"?

74

In questo articolo del 2003 di Stephen Figgins su linuxdevcenter.com , BitTorrent di Bram Cohen viene descritto come utilizzando il modello di progettazione "Correggi tutto".

A less common approach that both makes BitTorrent harder to grasp, but worthy of study, is Cohen's use of idempotence. A process is idempotent when applying it more than once causes no further changes. Cohen says he uses a design pattern he calls "Fix Everything," a function that can react to a number of changes without really noting what all it might change. He explains, "you note the event that happened, then call the fix everything function which is written in this very idempotent manner, and just cleans up whatever might be going on and recalculates it all from scratch." While idempotence makes some difficult calculations easier, it makes things a little convoluted. It's not always clear what a call is going to change, if anything. You don't need to know in advance. You are free to call the function, just to be on the safe side.

Questo suona piuttosto bello a prima vista.

Tuttavia, mi sembra che chiamare una funzione iddeterminata "aggiusta tutto" possa migliorare la robustezza del sistema al costo dell'efficienza e potenzialmente rovinare il sistema di contenimento (che potrebbe preferire processi che pianificano ed eseguono con cura).

Non posso dire di averlo già usato prima, però. Inoltre non riesco a trovare la fonte per la sua applicazione online (ma ho trovato questo che afferma di basarsi su di esso.). Né posso trovare riferimenti ad esso al di fuori di questo articolo (e considero il mio google-fu abbastanza buono) ma ho trovato una voce per " Idempotent Capability "su SOApatterns.org .

Questa idea è meglio conosciuta con un altro nome?

Che cos'è il motivo di progettazione "Correggi tutto"? Quali sono i suoi pro e contro?

    
posta Aaron Hall 19.04.2017 - 17:32
fonte

5 risposte

100

Supponiamo che tu abbia una pagina HTML piuttosto complicata: se selezioni qualcosa in un menu a discesa, potrebbe apparire un altro controllo o potrebbero cambiare i valori di un terzo controllo. Ci sono due modi per approcciare questo:

  1. Scrivi un gestore separato, per ciascun controllo, che risponde agli eventi su quel controllo e aggiorna altri controlli secondo necessità.

  2. Scrivi un singolo gestore che guarda lo stato di tutti i controlli sulla pagina e solo corregge tutto .

La seconda chiamata è "idempotente" perché è possibile chiamarla più volte e i controlli saranno sempre organizzati correttamente. Mentre la prima chiamata (s) può avere problemi se una chiamata è persa o ripetuta, ad es. se uno dei gestori esegue un interruttore.

La logica per la seconda chiamata sarebbe un po 'più oscura, ma devi solo scrivere un gestore.

E puoi sempre utilizzare entrambe le soluzioni, chiamando la funzione "aggiusta tutto" come necessario "solo per essere al sicuro."

Il secondo approccio è particolarmente piacevole quando lo stato può provenire da fonti diverse, ad es. dall'input dell'utente rispetto al reso dal server. In ASP.NET, la tecnica gioca molto bene con il concetto di postback, perché esegui semplicemente la correzione di tutte le funzioni ogni volta che esegui il rendering della pagina.

Ora che ho menzionato eventi persi o ripetuti e ottenuto lo stato da fonti diverse, penso che sia ovvio come questo approccio si adatti bene a uno spazio problematico come quello di BitTorrent.

Contro? Beh, l'ovvio problema è che c'è un successo in termini di prestazioni perché è meno efficiente andare avanti tutto tutto il tempo. Ma una soluzione come BitTorrent è ottimizzata per ridimensionare, non scalare, quindi va bene per quel genere di cose. A seconda del problema che stai cercando di risolvere, potrebbe non essere adatto a te.

    
risposta data 19.04.2017 - 17:49
fonte
15

Penso che l'articolo sia un po 'datato perché mentre lo leggo, questa non è affatto un'idea affatto ortodossa o nuova. Questa idea è presentata come un modello separato quando è solo una semplice implementazione di Observer. Ripensando a quello che stavo facendo in quel momento, ricordo di aver lavorato sulla logica per sedermi dietro un'interfaccia piuttosto complessa con un numero di pannelli diversi con dati che erano interdipendenti. L'utente può modificare i valori e / o eseguire una procedura di ottimizzazione e in base a tali azioni, sono stati generati eventi che l'interfaccia utente ascolta e aggiorna secondo necessità. Durante lo sviluppo si sono verificati numerosi problemi in cui alcuni pannelli non si aggiornavano quando avrebbero dovuto. La correzione (rimanendo all'interno del progetto) era di generare eventi da altri eventi. Alla fine, quando tutto ha funzionato correttamente, quasi tutti i cambiamenti hanno comportato l'aggiornamento di tutti i pannelli. Tutta la complessità del tentativo di isolare quando un determinato pannello doveva essere aggiornato era inutile. E non importava comunque. Era in effetti un'ottimizzazione prematura. Avrei risparmiato un sacco di tempo e fatica semplicemente collassando tutto in un singolo evento che ha rinfrescato tutto.

Esistono innumerevoli sistemi progettati in "aggiustare tutto" o aggiornare in qualsiasi modo. Pensa a tutte le interfacce CRUD che aggiungono / aggiornano una riga e quindi eseguono la query sul DB. Questo non è un approccio esotico, è solo l'ovvia soluzione non intelligente. Devi rendertene conto che nel 2003 era il culmine della "febbre da modello". Da quello che ho potuto dire, la gente pensava che nominare nuovi modelli sarebbe stato il loro percorso verso la fama e la ricchezza. Non fraintendermi, penso che il concetto di un modello sia estremamente utile per descrivere le soluzioni in astratto. Le cose sono andate un po 'fuori dai binari. È sfortunato perché ha creato molto cinismo riguardo al concetto di modello in generale. È solo in questo contesto che ha senso parlare di questa come una soluzione "non ortodossa". È simile all'ortodossia attorno agli ORM o ai contenitori DI. Non usarli è considerato non ortodosso anche se la gente aveva costruito software molto prima che questi strumenti esistessero e in molti casi quegli strumenti sono eccessivi.

Quindi torna a 'aggiustare tutto'. Un semplice esempio è il calcolo dei mezzi. La soluzione semplice è sommare i numeri e dividere per la cardinalità dei valori. Se aggiungi o modifichi un numero, lo fai di nuovo, dall'inizio. Puoi tenere traccia della somma e del conteggio dei numeri e quando qualcuno aggiunge un numero, aumenti il conteggio e lo aggiungi alla somma. Ora non stai aggiungendo di nuovo tutti i numeri. Se hai mai lavorato con Excel con una formula che fa riferimento a un intervallo e modificato un singolo valore in quell'intervallo, hai un esempio del modello "aggiusta tutto", ovvero qualsiasi formula che abbia un riferimento a quell'intervallo verrà ricalcolata indipendentemente dal fatto quel valore era rilevante (es. usando qualcosa come sumif ()).

Questo non vuol dire che questa non è una scelta intelligente in un dato contesto. Nell'esempio medio, diciamo che ora dobbiamo supportare gli aggiornamenti. Ora ho bisogno di conoscere il vecchio valore in qualche modo e solo modificare la somma per il delta. Niente di tutto questo è davvero così impegnativo finché non si considera di provare a farlo in un ambiente distribuito o concorrente. Ora devi gestire tutti i tipi di problemi di temporizzazione spinosi e probabilmente finirai per creare un collo di bottiglia importante che rallenta molto di più il ricalcolo.

Il risultato è che l'approccio "aggiusta tutto" o "aggiorna tutto" è molto più facile da ottenere. Puoi far funzionare un approccio più sofisticato ma è molto più complicato e quindi più probabile che sia difettoso. Inoltre, in molti contesti, l'approccio "aggiorna tutto" può essere più efficiente. Ad esempio, gli approcci di copia su scrittura sono generalmente più lenti per gli approcci a thread singolo, ma quando si dispone di una concorrenza elevata, è possibile evitare i blocchi e quindi fornire prestazioni migliori. In altri casi, può consentire di eseguire modifiche in gruppo in modo efficiente. Quindi, per la maggior parte dei problemi, probabilmente vorrai iniziare con un approccio di aggiornamento a meno che tu non abbia una ragione specifica per cui non puoi farlo e quindi preoccuparti di fare qualcosa di più complesso una volta che ne hai bisogno. Un'implementazione funzionante alla quale è possibile eseguire un test di regressione è di per sé preziosa, anche se è lenta.

    
risposta data 19.04.2017 - 19:12
fonte
4

Non sono sicuro che si tratti di un "modello di progettazione", ma classificherei quel tipo di comportamento come configurazione dello stato finale o configurazione dello stato desiderata , nella vena di Puppet, Chef o Powershell DSC.

Queste soluzioni di solito operano a livello di gestione dei sistemi, non a livello di business logic come la domanda descrive, ma è effettivamente lo stesso paradigma, e sebbene tali strumenti siano di solito dichiarativi, gli stessi principi possono essere applicati nel codice procedurale o scripting.

    
risposta data 19.04.2017 - 19:31
fonte
1

L'ho usato principalmente all'interno delle interfacce utente. La cosa bella è che lo scrivi una sola volta e gestisce ogni cosa, dal caso più semplice a quello più difficile, egualmente bene (ad esempio se l'utente ruota lo schermo, o su un laptop / desktop se l'utente ridimensiona una finestra, e praticamente tutto cambia ).

Non ci sono molti motivi per preoccuparsi dell'efficienza. Nell'interfaccia utente, le cose costose sono cose come ridisegnare un oggetto che è stato spostato. Il calcolo in cui ogni elemento va e quanto è grande è di solito abbastanza veloce. Tutto quello che devi assicurarti è che ogni volta che trovi che un oggetto deve rimanere esattamente nel posto in cui appartiene, non viene eseguito alcun codice per spostarlo. I veri cambiamenti sono tutte cose che dovevi fare comunque.

    
risposta data 29.08.2017 - 01:00
fonte
0

Suona come principi di programmazione reattiva. "Correggi tutto" guarda allo stato "principale" corrente e diffonde tutto il resto che dovrebbe essere interessato - "stati calcolati". Se si ottimizza questa derivazione, potrebbe raggiungere un'efficienza elevata, a-la React, se le prestazioni in modo ingenuo potrebbero non essere ottimali anche se potrebbero comunque essere abbastanza veloci.

    
risposta data 28.08.2017 - 21:24
fonte

Leggi altre domande sui tag