È un singleton con un metodo di aggiornamento e una verifica dello stato del software un modello valido?

0

Lo stack overflow ha suggerito che questa domanda sia la più adatta a me. Normalmente lavoro in C #, ma attualmente sto lavorando a un'applicazione vb.net net. Quindi sentiti libero di rispondere con vb.Net o c # ...

Essenzialmente ho un singleton che fa tutto il lavoro per ottenere le impostazioni globali che sono memorizzate nel database; ma c'è un'interfaccia (modulo di dialogo) che consente a quelle impostazioni di cambiare.

Quindi quello che ho fatto è stato creare un singleton che nella prima istanza (solo) esegue il metodo di aggiornamento pubblico. Se, tuttavia, un utente apre la finestra di dialogo delle impostazioni, il singleton viene istanziato e il comando di aggiornamento viene richiamato separatamente nel caso in cui l'utente abbia apportato modifiche alle impostazioni nella finestra di dialogo delle impostazioni ... è l'unico posto in cui eseguo il metodo di aggiornamento all'esterno dell'istanza iniziale dell'oggetto Singleton. È plausibile che un altro sviluppatore errante possa eseguire in modo irresponsabile il metodo di aggiornamento più e più volte, ma non danneggerebbe nulla tranne rallentare l'applicazione - e questa è la ragione principale per cui volevo usare un singleton, perché ci sono casi in cui con le chiamate al le impostazioni vengono fatte centinaia se non migliaia di volte in loop; che rallenterebbe davvero l'applicazione, e anche le impostazioni vengono chiamate da molte posizioni casuali a seconda di cosa fa l'utente ... perché non uso un semplice DTO, beh, questo è descritto di seguito.

L'altra cosa pazza di questa applicazione è che più "ambienti" possono essere eseguiti nello stesso thread, ognuno con impostazioni completamente diverse (lunga storia). Il modo in cui i precedenti sviluppatori lo gestivano effettuando una chiamata per aggiornare un DTO delle impostazioni ogni volta che si verificava un cambiamento o un cambiamento nelle impostazioni o "ambiente" o all'avvio dell'applicazione. In una ricerca ci sono circa 40 località ... sembra matto per me. Questo è in cima alle centinaia di chiamate a cui si accede al DTO. Voglio che questo singleton faccia il lavoro pesante e verifichi in quale ambiente si trova l'app e recuperi le impostazioni solo una volta dal database - tranne in quella occasione con la finestra di dialogo delle impostazioni che ho menzionato sopra, dove viene invocato il metodo di aggiornamento.

Risultato finale, un nocciolo singleton ... Di seguito è riportata una versione semplificata del codice. Fondamentalmente, sto chiedendo se questo è un modello ragionevole, o ce n'è uno migliore per questo? Si noti che un potenziale svantaggio della mia soluzione è che devo ancora effettuare una chiamata al database, come controllo per il database corrente, ogni volta che questa classe viene istanziata. Grazie per il feedback.

   Public Class MySingleton

        Private Shared _Instance As MySingleton = Nothing

        Private _ExampleSetting As String

        Private _CurrentDatabase as DBDatabase

        Public Shared ReadOnly Property GetInstance() As MySingleton
            Get
                If _Instance Is Nothing Then
                      _Instance = New MySingleton()
                ElseIf _CurrentDatabase <> GetCurrentDataBase() Then 
                      _Instance = New MySingleton()
                End If

                Return _Instance
            End Get
        End Property

        Public ReadOnly Property ExampleSetting As String
            Get
                Return _ExampleSetting
            End Get
        End Property


        Private Sub New()

            Update()

        End Sub


        Public Sub Update()

            _CurrentDatabase  = GetCurrentDataBase()

            _ExampleSetting = _CurrentDatabase.GetSetting("exampleSetting")

        End Sub

    End Class
    
posta Edward Bagby 01.02.2017 - 15:38
fonte

3 risposte

6

Il tuo "singleton" non è affatto un singleton. Si tratta di una cache di dati, che può comportare diverse parti della tua app con versioni diverse di quella cache. Nel codice C #, poiché il mio VB.Net è debole:

var instance1 = MySingleton.GetInstance();
// assume instance1.ExampleSetting would return "foo"

// do something that changes ExampleSetting to bar, such that
// _CurrentDatabase <> GetCurrentDataBase() is now true

var instance2 = MySingleton.GetInstance(); // new instance
var x = instance1.ExampleSetting; // will be foo
var y = instance2.ExampleSetting; // will be bar

Solo perché stai sovrascrivendo il _Instance statico con una nuova istanza non influirà sui riferimenti alle istanze precedenti detenute da altre parti del codice. Stai facendo affidamento sullo sviluppatore chiamando MySingleton.GetInstance() ogni volta per ottenere l'ultimo "singleton".

Aggiorna

Per rispondere alla domanda "c'è un modo migliore", una soluzione è usare l'iniezione di dipendenza. Piuttosto che avere un not-quite-singleton accessibile a livello globale, crea invece solo un'istanza di MySingleton e passa a tutte le parti del sistema che ne hanno bisogno. Quindi, ogni volta che viene interrogato, può controllare se il database è cambiato e si aggiorna da solo, invece di generare una nuova istanza.

    
risposta data 01.02.2017 - 16:08
fonte
1

L'essenza di Singleton è che può esserci solo una. C'è una sola istanza di una classe che viene creata quando è necessaria la prima volta, non viene mai creata un'altra istanza e l'istanza rimane attiva finché l'app è in esecuzione. Quindi quello che hai non è un singleton.

Ed è assolutamente legale e ci si aspetta che qualche bit di codice ottenga un riferimento a quel una volta di Singleton e utilizzi tale riferimento per sempre. Quindi non vi è assolutamente alcun motivo per ritenere che una parte di codice chiamerà mai GetInstance () più di una volta.

Sembra che il tuo GetCurrentDatabase () sia uno stato globale che viene modificato in modo incontrollato. Tutto ciò che è riuscito a fare è stato trasformare MySingleton () anche nello stato globale che è stato modificato in modo incontrollato. Direi che vuoi singoli oggetti, ognuno creato dal codice che vuole accedere ai dati in modi diversi, e questi oggetti possono parlare con un Singleton che ottimizza l'accesso nel miglior modo possibile.

    
risposta data 01.02.2017 - 20:52
fonte
1

Ad un'ispezione più ravvicinata, come ha identificato @ David Arno, questo non è un singleton. Il valore restituito da GetInstance varia potenzialmente su ogni chiamata.

Inoltre (e questo potrebbe essere semplicemente la mia mancanza di conoscenza sulla semantica VB) il fatto che non sembri avere restrizioni sull'uso del costruttore per la tua classe singleton significa che i clienti sono liberi di creare le proprie istanze.

Singleton ha una definizione ben compresa nei circoli di sviluppo del software. Quello che hai non è un "singleton", non è un singleton.

Non c'è nulla di sbagliato nello stato interno del singleton che cambia (purché ci sia solo una sua istanza), quindi se le tue proprietà individuali dovessero controllare se esistesse o meno un database e determinare il valore di ritorno in quel punto , potresti ancora conservare% sem_de% co_de. Indipendentemente dal fatto che tu possa eseguire questa operazione su scala è una domanda diversa.

    
risposta data 01.02.2017 - 16:08
fonte

Leggi altre domande sui tag