Un contesto globale impila un odore di codice?

0

Mi piacerebbe sentire argomenti a favore o contro un piano che sto considerando. Ho una grande rete di nodi ognuno dei quali ha proprietà con valori vettoriali. L'accesso a queste proprietà (lettura o scrittura) richiede un timestamp.

Piano A: passa il timestamp a ogni metodo che accederà alle proprietà (e ad ogni metodo che chiama quei metodi, ecc.)

Piano B: avere una variabile globale che è uno stack di contesto. Utilizzando un gestore di contesto, quando viene inserito un contesto, inserire un nuovo timestamp nello stack; aprilo all'uscita. L'accesso alla proprietà utilizzerà lo stack di contesto per fornire il timestamp.

I pros per pianificare A: più reti possono essere eseguite in parallelo facilmente (anche se non ho bisogno di più reti da eseguire). È facile vedere tutte le dipendenze perché non ci sono dipendenze nascoste.

I professionisti del piano B: il codice che opera sulle proprietà è più semplice. Può solo utilizzare l'accesso ai membri per leggere e scrivere: self.b[2] += self.a anziché self.b.increment(context, self.a, 2) .

Quale piano dovrei scegliere? Ho perso eventuali pro e contro?

    
posta Neil G 27.04.2016 - 23:12
fonte

2 risposte

2

B è più difficile da parallelizzare, ma non lo stai facendo. Quindi, giusto? No, è ancora una brutta cosa, ed ecco perché:

Quel parametro in più che stai cercando di evitare è lì per un motivo. Indica una dipendenza dei dati che potrebbe non essere altrimenti ovvia. Questo rende più facile ragionare il codice dopo che è trascorso il tempo e non si ha più familiarità con esso. Queste dipendenze semplificano il refactoring e lo sviluppo di nuove funzionalità, riducendo la quantità di "azione spettrale a distanza" di cui ti devi preoccupare. Se qualcosa non è un parametro di una determinata funzione, cambiare quella cosa non dovrebbe influire su quella funzione. Se vuoi spostare o copiare una chiamata di funzione in una parte diversa della tua base di codice, devi solo spostare o copiare tutti i suoi parametri su dove vuoi chiamarla; non devi smanettare con qualche stato globale per farlo funzionare correttamente. Se vuoi combinare due funzioni, devi solo prendere l'unione dei loro parametri e controllare l'interferenza tra questi parametri; non devi preoccuparti di come interagiscono con i globali. Ogni forma di refactoring è più facile senza giochi globali in gioco.

Ora, una certa quantità di stato globale può essere inevitabile, per quasi tutte le lingue tranne Haskell, che chiaramente non stai usando. Ad esempio, la maggior parte delle forme di I / O sono operazioni globali poiché influenzano il mondo esterno. Unix ha un numero di parametri di processo globali che possono essere difficili da evitare completamente (ad esempio la directory corrente, la umask, ecc.). Ma questo non giustifica andare in giro inventando nuovi tipi di stato globale. Lo stato globale (mutabile) è sempre colpevole fino a prova contraria.

Potrebbe essere che ci sia un problema di progettazione più fondamentale con questo oggetto context . Forse potresti renderlo una variabile di istanza, in modo che le proprietà possano accedervi e scrivere codice più semplice basato sulle proprietà. Ma a quel punto, probabilmente vorrai scomporlo nelle sue parti costitutive, piuttosto che avere una sola variabile self.context . self dovrebbe essere il tuo "sacco di contesto casuale"; avere un self.context non ha molto senso. O forse c'è un altro problema di base che non riesco a vedere senza saperne di più sulla base di codice.

    
risposta data 27.04.2016 - 23:43
fonte
1

Il piano principale Un vantaggio è il test. Vuoi eseguire i tuoi test unitari in parallelo, giusto? Bingo, più reti in parallelo. Per non parlare dei semplici problemi di testabilità con il contesto globale.

    
risposta data 27.04.2016 - 23:31
fonte

Leggi altre domande sui tag