Resiste la tentación del patrón Singleton
Autor: Sam Saariste

El patrón Singleton resuelve muchos de tus problemas. Sabes que sólo necesitas una sola instancia. Tienes una garantía de que esta instancia fue inicializada antes de ser usada. Mantiene tu diseño simple y con un sólo punto de acceso global. Todo está bien. ¿Qué es lo que no me gusta de este clásico patrón de diseño?

Pues mucho, resulta ser. Puede ser tentador, pero la experiencia me mostró que la mayoría de los Singleton hacen realmente más daño que bien. Dificultan las pruebas y dañan la capacidad de mantenimiento. Desafortunadamente, esta sabiduría adicional no está tan propagada como debería y los Singletons continúan siendo irresistibles para la mayoría de los programadores. Pero vale la pena resistirse:

  • El requisito de instancia única es con frecuencia imaginado. En muchos casos es pura especulación de que no se necesitarán instancias adicionales en el futuro. Difundir tales propiedades especulativas, a través del diseño de la aplicación, está destinado a causar dolor en algún momento. Los requerimientos cambiarán. El buen diseño lo adopta. Los Singleton no.
  • Los Singleton causan dependencia implícita entre unidades de código conceptualmente independientes. Esto es problemático porque están ocultos e introducen acoplamiento innecesario entre las unidades. Este olor del código se pudre cuando intentas escribir pruebas unitarias, las cuales dependen de soltar el acoplamiento y de la habilidad de sustituir selectivamente una implementación simulada (mock) de una real. Los Singleton previenen la simulación directa.
  • Los Singleton también llevan estado persistente implícito, lo que dificulta más las pruebas unitarias. Las pruebas unitarias dependen de que sean independientes entre sí, así las pruebas pueden ser ejecutadas en cualquier orden y el programa puede ser configurado a un estado conocido antes de la ejecución de cada prueba unitaria. Una vez que hayas introducido Singleton con estado mutable, esto puede ser más difícil de llevar a cabo. Además, dicho estado globalmente accesible hace más difícil razonar sobre el código, especialmente en ambientes multihilos.
  • Los multihilos introducen futuras fallas en el patrón Singleton. El bloqueo directo al acceso no es muy eficiente, así es como el llamado patrón de doble revisión de bloqueo (DCLP) ha ganado popularidad. Desafortunadamente, esto puede llevar una forma adicional de atracción fatal. Resulta ser que muchos lenguajes DCLP no son thread-safe e, incluso cuando lo son, aún hay oportunidades de sutiles errores.

El limpiado de Singleton puede presentar un reto final:

  • No hay soporte para matar explícitamente a un Singleton, lo cuál puede ser un problema delicado en algunos contextos. Por ejemplo, en una arquitectura de plug-ins en la que un plug-in sólo puede ser descargado de forma segura después de que todos sus objetos han sido limpiados.
  • No hay orden implícito de limpieza de Singleton al salir del programa. Esto puede ser problemático para aplicaciones que contienen Singleton con interdependencias. Cuando se cierra dicha aplicación, un Singleton puede acceder a otra que ya ha sido destruida.

Algunas de estas deficiencias pueden ser superadas mediante la introducción de mecanismos adicionales. Sin embargo, esto viene con el costo de complejidad adicional en código que se podría haber evitado escogiendo un diseño alternativo.

Por lo tanto, restringe el uso del patrón Singleton a las clases que realmente nunca deber ser instanciadas más de una vez. No uses un Singleton como punto de acceso global desde código arbitrario. En vez de ello, el acceso directo al Singleton debería ser desde sólo unos pocos lugares definidos, donde pueda dársele vuelta vía una interfaz hacia otro código. Este otro código no lo sabe y así no depende de si un Singleton o cualquier otro tipo de clase implementa la interfaz. Esto rompe la dependencia que impide las pruebas unitarias y mejora la capacidad de mantenimiento. Así que, la próxima vez que estés pensando en implementar o acceder a un Singleton espero que hagas una pausa y lo pienses de nuevo.

Traducción: Espartaco Palma

Leer contribución original