Stiamo osservando i cattivi effetti dello stato globale in questo progetto?

3

Ho letto le risposte a Perché lo stato globale è così malvagio? , e penso che le conseguenze negative non si applichino in questa situazione. Tuttavia, questo è quello che tutti dicono poco prima di essere colpiti da un pianostrong in caduta e le mie lezioni di architettura del software sono state qualche anno fa, quindi ...

Stiamo sviluppando un'applicazione di chat desktop in Python. In quella applicazione, c'è uno stato intrinsecamente globale: configurazione account, classi client (dalla libreria del protocollo chat) per quegli account, conversazioni aperte, ecc.

Nel progetto attuale, utilizziamo singole istanze globali per il controller account e il controller client (gestendo gli oggetti client dalla libreria chat che stiamo utilizzando) e il controller di conversazione (gestendo le astrazioni di conversazione per le sessioni di chat comprese le chat di gruppo ). Queste istanze globali sono disponibili ovunque tramite un semplice import foo.app as app . I controller hanno modelli associati e le visualizzazioni di sola lettura su questi modelli possono essere istanziate in modo indipendente in vari punti dell'applicazione.

Si applicano le seguenti osservazioni:

  • Il test delle unità funziona bene finora: possiamo tranquillamente deridere quelle istanze globali con Pythons unittest.mock (infatti, le istanze sono solo inizializzate durante l'effettivo avvio dell'applicazione, quindi sono None altrimenti - > instant e errore evidente se non viene deriso ma utilizzato nei test).
  • La modifica dello stato dei dati globali associati ai controller passa solo attraverso i controller; e la modifica dello stato emette segnali di callback ben definiti in modo che i consumatori dello stato possano ottenere aggiornamenti.
  • Il codice ha concurrency, ma sta usando l'asyncio di Python: questo implica multitasking cooperativo, quindi i punti in cui altri task possono interferire sono ben definiti e ovvi nel codice (quando usiamo thread reali, stato globale non sarà possibile accedere direttamente). Quindi è sicuro assumere che lo stato globale non cambi all'interno di un metodo (non di coroutine).
  • La maggior parte degli usi dello stato globale sono semplici ricerche del tipo "Quale oggetto client è associato all'account X?", "Ottieni l'oggetto conversazione sull'account X con peer Y", "Quali account e identità esistono?" e iscrivendosi agli aggiornamenti.

Ora mi chiedo: abbiamo trascurato qualcosa? E se sì, quale sarebbe la correzione appropriata? Sento che questo progetto potrebbe funzionare abbastanza bene, ma temo che potremmo aver trascurato qualcosa di rilevante che cadrà in piedi in un secondo momento.

    
posta Jonas Schäfer 13.07.2017 - 10:48
fonte

3 risposte

3

Se si spinge qualche regola abbastanza da ridurla a una scelta soggettiva. Ma lo "stato globale è cattivo" è circa il canone che ottieni.

Sappiamo tutti che a volte è più rapido utilizzare lo stato globale per risolvere un problema. O forse un particolare framework che stiamo usando limita altre opzioni a tal punto che lo Stato Globale è una soluzione accettabile.

Ma queste sono posizioni estreme in cui accettiamo di fare una 'brutta cosa' (tm) e promettiamo di fare attenzione.

Hai affermato come sei riuscito ad evitare alcune delle trappole dello stato globale, ma non quello che la estrema pressione, denaro, tempo o limitazione tecnica è stata forzata tu per percorrere quella via!

Dato che eliminare lo stato globale è abbastanza semplice ed è quasi universalmente considerato un codice "migliore". Perché diavolo non lo faresti ???

Se l'argomento è "lo stato globale non è male, guarda questo codice", l'unica cosa da fare è scrivere la stessa app in entrambi i modi e vedere quale ha meno linee di codice, o qualsiasi misura di bontà che vuoi applicare . Ma dovresti pubblicare entrambe le basi complete del codice o collegarle a github o qualcosa del genere.

Presumibilmente sarebbero entrambi abbastanza simili e discuteremo se essere in grado di eseguire test unitari contemporaneamente ecc. dovrebbe essere parte della "misura della bontà"

    
risposta data 13.07.2017 - 12:47
fonte
2

IMHO c'è un grosso malinteso.

Il problema non è tanto stato globale ma variabili globali .

Ogni applicazione deve mantenere un qualche tipo di stato globale . Il punto è che non dovresti farlo tramite variabile globale o il modello di progettazione singelton (che in pratica è anche una variabile globale).

Non c'è niente di sbagliato nell'avere una singola istanza di una classe consegnata a molti altri oggetti per scambiare informazioni con essa. Ma non dovrebbe essere accessibile come una variabile globale .

    
risposta data 13.07.2017 - 12:54
fonte
2

Se hai un programma in cui la parte principale è effettivamente disaccoppiata da "stato globale" (o può essere disaccoppiata per testare "prendendo in giro le istanze globali" , come hai scritto), puoi interpreta tutti i dati di stato globali come dati di input e tutte le mutazioni allo stato globale come dati di output , senza stato globale all'interno dei componenti principali.

Se il programma si adatta completamente a questo modello e la parte centrale non contiene nessuno stato "nascosto" "malvagio", allora il tuo progetto va bene. Nota ci sono ancora "parti satellite" per collegare lo "stato globale" alle parti principali. Per mantenere il programma mantenibile ed evolutivo, il tuo obiettivo dovrebbe essere quello di mantenere quelle "parti satellite" il più piccole e semplici possibile - altrimenti queste parti hanno un certo rischio di diventare il punto debole del tuo progetto.

    
risposta data 13.07.2017 - 16:09
fonte

Leggi altre domande sui tag