Pregunta

¿Cuándo NO deberías usar una clase de singleton aunque podría ser muy tentador hacerlo? Sería muy bueno si tuviéramos una lista de los casos más comunes de 'singletonitis' que deberíamos tener cuidado de evitar.

¿Fue útil?

Solución

No use un singleton para algo que pueda evolucionar en un recurso multiplicable.

Esto probablemente suene tonto, pero si declara algo como un singleton, está haciendo una declaración muy fuerte de que es absolutamente único. Estás construyendo código a su alrededor, cada vez más. Y luego, después de miles de líneas de código, descubre que no es un singleton en absoluto, tiene una gran cantidad de trabajo por delante porque todos los demás objetos esperan " el " objeto sagrado de la clase WizBang para ser un singleton.

Ejemplo típico: " Solo hay una conexión de base de datos que tiene esta aplicación, por lo que es un singleton. " - Mala idea. Es posible que desee tener varias conexiones en el futuro. Mejor cree un grupo de conexiones de base de datos y llénelo con una sola instancia. Funciona como un Singleton, pero todos los demás códigos tendrán un código que se pueda crecer para acceder al grupo.

EDITAR: entiendo que, en teoría, puedes extender un singleton a varios objetos. Sin embargo, no existe un ciclo de vida real (como agrupación / desunión), lo que significa que no hay propiedad real de los objetos que se han entregado, es decir, el multi-singleton ahora tendría que ser apátrida para ser utilizado simultáneamente por diferentes métodos y subprocesos.

Otros consejos

Bueno, los singletons en su mayor parte simplemente están haciendo las cosas estáticas de todos modos Entonces, o bien estás haciendo que los datos sean globales, y todos sabemos que las variables globales son malas o que estás escribiendo métodos estáticos y eso no es muy OO, ¿verdad?

Aquí es un comentario más detallado sobre por qué los singletons son malos, por Steve Yegge. Básicamente, no debes usar singletons en casi todos los casos, realmente no puedes saber que nunca será necesario en más de un lugar.

Sé que muchos han respondido con " cuando tienes más de un " ;, etc.

Ya que el póster original quería una lista de casos en los que no deberías usar Singletons (en lugar de la razón principal), te enviaré un mensaje con:

¡Siempre que lo estés utilizando porque no puedes usar un global!

La cantidad de veces que he tenido un ingeniero subalterno que ha usado un Singleton porque sabía que no aceptaba globales en las revisiones de códigos. A menudo, se sorprenden cuando les digo que todo lo que hicieron fue reemplazar un patrón global con un patrón de Singleton, ¡y aún tienen un modelo global!

Soy culpable de uno grande hace unos años (afortunadamente, he aprendido mi lección desde entonces).

Lo que sucedió es que subí a bordo de un proyecto de aplicación de escritorio que se convirtió a .Net desde VB6, y fue un verdadero desastre. Cosas como funciones de 40 páginas (impresas) y ninguna estructura de clase real. Construí una clase para encapsular el acceso a la base de datos. No es un nivel de datos real (todavía), solo una clase base que un nivel de datos real podría usar. En algún lugar tuve la brillante idea de hacer de esta clase un singleton. Funcionó bien durante aproximadamente un año, y también tuvimos que crear una interfaz web para la aplicación. El singleton terminó siendo un gran cuello de botella para la base de datos, ya que todos los usuarios de la web tenían que compartir la misma conexión. Una vez más ... lección aprendida.

Mirando hacia atrás, probablemente en realidad fue la elección correcta por un corto tiempo, ya que obligó a los otros desarrolladores a ser más disciplinados sobre su uso y los hizo conscientes de los problemas de alcance que antes no eran un problema en el mundo VB6. Pero debería haberlo cambiado de nuevo después de unas pocas semanas antes de que tuviéramos demasiada información al respecto.

Aquí hay una perorata de mi amigo Alex Miller ... No se enumera exactamente " cuando NO debe usar un singleton " pero es una publicación completa, excelente y argumenta que solo se debe usar un singleton en raras ocasiones, en todo caso.

Los Singletons son virtualmente siempre una mala idea y generalmente son inútiles / redundantes, ya que son solo una simplificación muy limitada de un patrón decente.

Mira cómo funciona la inyección de dependencia. Resuelve los mismos problemas, pero de una manera mucho más útil: de hecho, encuentra que se aplica a muchas más partes de su diseño.

Aunque puedes encontrar bibliotecas DI por ahí, también puedes rodar una básica, es bastante fácil.

Intento tener un solo singleton: una inversión del objeto de localización de control / servicio.

IService service = IoC.GetImplementationOf<IService>();

Una de las cosas que lo convierten en una pesadilla es si contiene el estado global modificable . Trabajé en un proyecto en el que se usaban Singletons por todo el lugar para cosas que deberían haberse resuelto de una manera completamente diferente (pasar estrategias, etc.) La " de-singletonification " Fue en algunos casos una reescritura importante de partes del sistema. Yo diría que en la mayor parte de los casos cuando las personas usan un Singleton, es simplemente incorrecto porque se ve bien en primer lugar, pero se convierte en un problema especialmente en las pruebas.

Cuando tiene varias aplicaciones ejecutándose en la misma JVM.

Un singleton es un singleton en toda la JVM, no solo en una aplicación. Incluso si varios subprocesos o aplicaciones parecen estar creando un nuevo objeto singleton, todos están usando el mismo si se ejecutan en la misma JVM.

A veces, supones que solo habrá una cosa, y luego te equivocas.

Ejemplo, una clase de base de datos. Usted asume que solo se conectará a la base de datos de su aplicación.

// Its our database! We'll never need another
class Database
{
};

¡Pero espera! Tu jefe dice, engancha a alguna otra base de datos de chicos. Digamos que desea agregar phpbb al sitio web y desea insertar su base de datos para integrar algunas de sus funciones. ¿Debemos hacer un nuevo singleton u otra instancia de base de datos? La mayoría de las personas están de acuerdo en que se prefiere una nueva instancia de la misma clase, no hay duplicación de código.

Prefieres tener

Database ourDb;
Database otherDb;

que la base de datos copy-past y make:

// Copy-pasted from our home-grown database.
class OtherGuysDatabase
{
};

La pendiente resbaladiza aquí es que puede dejar de pensar en crear una nueva instancia de clases y en su lugar comenzar a pensar que está bien tener un tipo para cada instancia.

En el caso de una conexión (por ejemplo), tiene sentido que no quiera hacer la conexión en sí, es posible que necesite cuatro conexiones, o que deba destruir y recrear la conexión una cantidad de veces.

Pero, ¿por qué no accede a todas sus conexiones a través de una única interfaz (es decir, administrador de conexión)?

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top