I singleton immutabili / apolidi sono cattivi?


12

Ultimamente c'è stata una sorta di rivoluzione contro i single, ma c'è qualcosa di sbagliato in loro se sono apolidi?

Conosco il discorso sull'uso eccessivo e tutto il resto ... questo vale per tutto, non solo per i singoli.


1
No. In linea di principio i single non sono male, sono solo massicciamente abusati.
Bart van Ingen Schenau,

3
cosa intendi con Ultimamente?
Manoj R,

5
@Joachim Sauer: perché dovresti sostituirlo; se è apolide puoi testarlo direttamente.
m3th0dman,

1
Se hai un singleton senza stato, allora fondamentalmente hai una classe di utilità statica, che ha la tendenza a crescere nel modello anti-God Class. Di solito puoi usare metodi statici invece nel contesto in cui sono usati (o ancora meglio: usa metodi di estensione in C #).
Spoike,

1
Possibile duplicato di Singleton senza alcuno stato
Caleth,

Risposte:


12
  > Are immutable/stateless singletons bad?
  • No se non dipendono da altri sistemi esterni.
    • Esempio: Stringutility che sfugge a HTML all'interno di una stringa.
    • Motivo: negli unittest non è necessario sostituirlo con un simulatore / simulatore.
  • Sì, se il singleton immutabile / stateless dipende da altri sistemi / servizi esterni e se si desidera eseguire unittesting (test in isolamento)
    • Esempio: un servizio che dipende da un servizio esterno di calcolatrice fiscale.
    • Motivo: per effettuare unittest con questo servizio (in isolamento) è necessario simulare / deridere i sistemi / servizi esterni.

Per maggiori dettagli vedi the-onion-architecture


  • Singleton-s può rendere i test unitari (isolati) più difficili / impossibili e
  • dipendenze / accoppiamenti nascosti possono essere visti come un problema, come spiegato da @yBee

Non vedo altri motivi per cui non usare Singletons.


Dovresti comunque deridere quel servizio web esterno se vuoi testare la tua classe, anche se non è un singleton (senza stato).
m3th0dman,

@ m3th0dman sono d'accordo
k3b

10

Dipende sempre dall'uso. Credo che la rivoluzione viene dal fatto, che ogni programmatore apprende questo schema come l' object oriented modello. La maggior parte dimentica di pensare a dove ha senso e dove no.
Questo, ovviamente, è vero per ogni modello. Solo usando i pattern non crei un buon codice o un buon software.

Se hai un singleton senza stato, perché non utilizzare una classe che offre solo metodi statici (o utilizzare una classe statica)?

Ecco alcuni post riguardanti variabili globali e singoli in generale.

Non sarei severo come l'autore, ma dimostra che per la maggior parte dei casi in cui pensi di aver bisogno di un singleton, non ne hai davvero bisogno.


1
Perché non usare una classe con metodi statici? Eredità per esempio ...
m3th0dman

3
@ m3th0dman: non sembra un buon posto per l'eredità.
Billy ONeal

@BillyONeal Puoi dire che qualcosa è buono o cattivo per l'eredità se conosci il modello di dominio, cosa deve essere modellato in quel modo ...
m3th0dman

2
@ m3th0dman: Erm, no. Posso essere abbastanza positivo senza sapere nulla del modello di dominio. L'ereditarietà è per comportamento polimorfico. Ma come singleton, non avrai un comportamento polimorfico.
Billy ONeal,

1
@ m3th0dman: perché per ottenere l'oggetto singleton è necessario specificare il nome del singleton nel sito di chiamata. Ciò significa che non stai usando il comportamento polimorfico. Ciò significa che la composizione è molto più flessibile dell'eredità.
Billy ONeal,

7

Non c'è nulla che un singleton stateless immutabile possa fare che una classe statica non può fare.

Non c'è semplicemente alcun motivo per aggiungere il livello extra di complessità che -> Instance () crea, mentre la semplice chiamata a un metodo statico sarà più chiara, più conservativa in termini di risorse e probabilmente più veloce.

Non è che si sbagliano. È che esiste un modo migliore per farlo. Ci sono scenari in cui i singoli ("stateful") normali sono la strada giusta da percorrere. Il male con singleton è che vengono spesso abusati, con gli stessi cattivi risultati delle variabili globali, ma ci sono casi specifici in cui l'uso di un singleton è semplicemente corretto. Non ci sono casi simili per gli apolidi.


Scommetto che puoi costruire alcuni casi in cui un Singleton ha alcuni vantaggi. A seconda dello scenario e del linguaggio di programmazione eventualmente (ad es. Sfruttando il caricamento lento).
StampedeXV

1
@StampedeXV: Sì, certamente un singleton con stato. Un apolide e immutabile - Sarei davvero curioso di sentire qualche esempio ma non trattengo il respiro.
SF.

Ok, hai ragione. Ho generalizzato la tua risposta un po 'lì. Neanche per gli apolidi immutabili non vedo alcun vantaggio.
StampedeXV

1
Con le classi che hanno solo funzioni statiche, non puoi usare l'ereditarietà / il polimorfismo che è un grande limite ...
m3th0dman

1
Non c'è nulla che un singleton stateless immutabile possa fare che una classe statica non può fare. bene, i metodi statici non possono implementare un'interfaccia, cosa che un singleton potrebbe
Michal M

3

Il problema principale con singleton è che nasconde le dipendenze e l'accoppiamento soprattutto se utilizzato in scenari di problematiche trasversali. Vedi Singletons sono bugiardi patologici o Perché i singleton sono malvagi per ulteriori letture.

Dall'altro lato, uno stato meno singleton, se non abusato, può essere utile e migliorare le prestazioni. Considera un esempio:

interface Interface
{
    void Method();
}

class StatelessSingleton : Interface
{
    public static readonly StatelessSingleton Instance = new StatelessSingleton();
    private StatelessSingleton() { }

    public void Method() { }
}

class User
{
    public User(Interface i) { /* ... */ }
}

Qui StatelessSingleton funge da implementazione predefinita dell'interfaccia e viene inserito nel costruttore User. Non esistono accoppiamenti codificati e dipendenze hiden. Non siamo in grado di utilizzare una classe statica a causa dell'interfaccia sottostante ma non c'è motivo di creare più di un'istanza di un valore predefinito. Ecco perché un singleton apolide sembra essere una scelta appropriata.

Tuttavia, forse dovremmo usare un altro modello per un'implementazione predefinita:

class Implementation : Interface
{
    private readonly Action _method;

    public Implementation()
    {
        _method = new Action(() => { /* default */ });
    }

    public Implementation(Action custom)
    {
        _method = custom;
    }

    public void Method()
    {
        _method();
    }
}

Colpisce le prestazioni rispetto a StatelessSingleton ma costituisce un'implementazione generica dell'interfaccia. Una soluzione simile viene utilizzata dall'interfaccia IProgress .

Anche in questo caso, perché consentire di creare più di un'implementazione del comportamento predefinito? Eppure possiamo combinare i due:

class Implementation : Interface
{
    public readonly Implementation Default = new Implementation();

    private readonly Action _method;

    private Implementation()
    {
        _method = new Action(() => { /* default */ });
    }

    public Implementation(Action custom)
    {
        _method = custom;
    }

    public void Method()
    {
        _method();
    }
}

In conclusione, credo che ci siano posti (come impostazioni predefinite raffigurate) in cui i Singleton sono utili. La definizione principale di Singleton afferma che non consente di creare più di un'istanza di una classe. È come l'energia nucleare. Può produrre un'energia o una bomba. Dipende dall'essere umano.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.