¿Son malos los singletons inmutables / sin estado?

12

Últimamente ha habido algún tipo de revolución contra los solteros, pero ¿hay algo malo en ellos si son apátridas?

Sé el uso excesivo y todo ... esto se aplica a todo, no solo a los solteros.

m3th0dman
fuente
1
No. Los singletons en principio no son malos, simplemente se usan en exceso.
Bart van Ingen Schenau
3
¿Qué quieres decir con Lately?
Manoj R
55
@Joachim Sauer: ¿Por qué necesitarías reemplazarlo? si no tiene estado, puede probarlo directamente.
m3th0dman
1
Si tiene un singleton sin estado, entonces básicamente tiene una clase de utilidad estática, que tiene una tendencia a convertirse en el antipatrón de la Clase Dios. Por lo general, puede usar métodos estáticos en el contexto en el que se usan (o incluso mejor: usar métodos de extensión en C #).
Spoike
1
Posible duplicado de Singleton sin ningún estado
Caleth

Respuestas:

12
  > Are immutable/stateless singletons bad?
  • No, si no dependen de otros sistemas externos.
    • Ejemplo: una Stringutility que escapa a html dentro de una cadena.
    • Motivo: en las pruebas unitarias no es necesario reemplazar esto con un simulacro / simulador.
  • Sí, si su singleton inmutable / sin estado depende de otros sistemas / servicios externos y si desea hacer pruebas unitarias (pruebas en aislamiento)
    • Ejemplo: un servicio que depende de un servicio web externo de calculadora de impuestos.
    • Motivo: para realizar pruebas unitarias con este Servicio (de forma aislada) debe simular / simular los Sistemas / Servicios externos.

Para más detalles ver the-onion-architecture


  • Singleton-s puede hacer que las pruebas unitarias (en forma aislada) sean más difíciles / imposibles y
  • las dependencias / acoplamientos ocultos pueden verse como un problema según lo explicado por @yBee

No veo otras razones por las que no usar Singletons.

k3b
fuente
Todavía tendría que burlarse de ese servicio web externo si desea probar su clase, incluso si no es un singleton (sin estado).
m3th0dman
@ m3th0dman estoy de acuerdo
k3b
10

Siempre depende del uso. Creo que la revolución viene del hecho de que cada programador aprende este patrón como el patrón orientado a objetos. La mayoría se olvida de pensar dónde tiene sentido y dónde no.
Esto, por supuesto, es cierto para cada patrón. Simplemente usando patrones no creas un buen código o un buen software.

Si tiene un singleton sin estado, ¿por qué no usar una clase que ofrezca solo métodos estáticos (o usar una clase estática)?

Aquí algunas publicaciones sobre variables globales y singletons en general.

No sería tan estricto como el autor, pero muestra que para la mayoría de los casos en los que crees que necesitas un singleton, realmente no lo necesitas.

StampedeXV
fuente
1
¿Por qué no usar una clase con métodos estáticos? Herencia, por ejemplo ...
m3th0dman
3
@ m3th0dman: No suena como un buen lugar para la herencia.
Billy ONeal
@BillyONeal Puede decir que algo es bueno o malo para la herencia si conoce el modelo de dominio, qué se
modelará de
2
@ m3th0dman: Erm, no. Puedo ser bastante positivo sin saber nada sobre el modelo de dominio. La herencia es por comportamiento polimórfico. Pero como singleton, no vas a tener un comportamiento polimórfico.
Billy ONeal
1
@ m3th0dman: Porque para obtener el objeto singleton se requiere especificar el nombre del singleton en el sitio de la llamada. Lo que significa que no estás usando un comportamiento polimórfico. Lo que significa que la composición es mucho más flexible que la herencia.
Billy ONeal
7

No hay nada que un singleton sin estado inmutable pueda hacer que una clase estática no pueda hacer.

Simplemente no hay razón para agregar el nivel adicional de complejidad que crea -> Instance (), mientras que la simple llamada a un método estático será más clara, más conservadora en términos de recursos y probablemente más rápida.

No es que estén equivocados. Es que hay una mejor manera de hacerlo. Hay escenarios en los que los singletons normales ("con estado") son el camino correcto. Lo malo de singleton es que a menudo se abusa de ellos, con los mismos malos resultados que las variables globales, pero hay casos específicos en los que usar un singleton es simplemente correcto. No hay tales casos para los apátridas.

SF.
fuente
Apuesto a que puedes construir algunos casos en los que un Singleton tiene algunas ventajas. Dependiendo del escenario y del lenguaje de programación posiblemente (por ejemplo, aprovechando la carga diferida).
StampedeXV
1
@StampedeXV: Sí, un singleton con estado ciertamente. Una apátrida e inmutable. Sería realmente curioso escuchar algún ejemplo, pero no contengo la respiración.
SF.
Ok, tienes un punto. Generalicé tu respuesta un poco allí. Para los apátridas inmutables tampoco veo ninguna ventaja.
StampedeXV
1
Con clases que solo tienen funciones estáticas, no puede usar herencia / polimorfismo, que es un gran límite ...
m3th0dman
1
No hay nada que un singleton sin estado inmutable pueda hacer que una clase estática no pueda hacer. bueno, los métodos estáticos no pueden implementar una interfaz, lo que podría hacer un singleton
Michal M
3

El principal problema con el singleton es que oculta las dependencias y se acopla especialmente cuando se usa en situaciones transversales. Vea Singletons son mentirosos patológicos o Why Singletons Evil para leer más.

Por otro lado, un estado menos único, si no se abusa, puede ser útil y mejorar el rendimiento. Considere un ejemplo:

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) { /* ... */ }
}

Aquí, StatelessSingleton actúa como implementación predeterminada de la interfaz y se coloca en el constructor de usuario. No hay acoplamientos codificados ni dependencias ocultas. No podemos usar una clase estática debido a la interfaz subyacente, pero no hay ninguna razón para crear más de una instancia de un valor predeterminado. Es por eso que un singleton sin estado parece ser una opción adecuada.

Sin embargo, tal vez deberíamos usar otro patrón para una implementación predeterminada:

class Implementation : Interface
{
    private readonly Action _method;

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

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

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

Alcanza el rendimiento con respecto a StatelessSingleton pero constituye una implementación genérica de la interfaz. La interfaz IProgress utiliza una solución similar .

Aunque de nuevo, ¿por qué permitir crear más de una implementación de comportamiento predeterminado? Sin embargo, podemos combinar los dos:

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();
    }
}

En conclusión, creo que hay lugares (como los valores predeterminados representados) donde los Singleton son útiles. La definición principal de Singleton establece que no permite crear más de una instancia de una clase. Es como la energía nuclear. Puede producir una energía o una bomba. Depende de los humanos.

yee
fuente