cómo refactorizar muchos singletons

7

Tengo un programa de Python de tamaño mediano (~ 5000 líneas de código), que he desarrollado a lo largo del tiempo, sin ningún plan en particular a medida que avanzaba. La arquitectura con la que he terminado consta de 5-6 objetos Singleton grandes, cada uno de los cuales maneja un aspecto específico de mi programa, como comunicaciones de base de datos, un servidor web, un cliente de recopilación de datos y cálculos internos.

Siento que usar varios singletons como este realmente no hace uso del verdadero beneficio de la programación OO, es decir, que le permite fácilmente crear numerosos objetos relacionados. Mis singletons también son bastante dependientes unos de otros, y si aumenté mucho el programa (por ejemplo, ~ 50 000 líneas), puedo ver que mi enfoque se convierte en código de espagueti.

Así que me pregunto si hay una mejor manera de estructurar mi programa. P.ej. ¿Deben mis singletons ser módulos separados? Pero entonces, ¿cómo me acercaría a los atributos que están muy bien organizados en mis objetos singleton? ¿Hay otras opciones de arquitectura?

No estoy muy familiarizado con los patrones de diseño (el libro de GOF está en mi lista de tareas pendientes), así que quizás haya diseños y / o patrones arquitectónicos que sean mejores para mi programa.

    
pregunta funklute 14.10.2015 - 09:51

2 respuestas

22

Muchos consideran a los Singletons como 'malvados', y aunque un patrón de Singleton tiene sus usos, son pocos y distantes entre sí. He trabajado con varios códigos de código grandes y casi siempre he logrado alejarlos de Singletons.

La forma más sencilla de eliminar singletons es:

  1. Introduzca una interfaz en la parte superior de su singleton : esto le permite separar el contrato de la implementación y reduce el acoplamiento que tiene con la implementación real
  2. Proporcione un configurador en su singleton para que pueda configurar la instancia de singleton desde una prueba de unidad : esto le permite "intercambiar" la instancia de singleton en una prueba de unidad.
  3. Cree las pruebas de unidad en la clase que desea cambiar : utilizando una simulación de la interfaz introducida en 1 y el configurador introducido en 2, ahora puede escribir pruebas de unidad en la clase.
  4. Inyecte el singleton en lugar de hacerlo de forma estática : en la clase que depende de su singleton, tenga una forma de inyectar ese singleton (a través de la interfaz creada en 1). Puede utilizar la inyección de constructor, los establecedores basados en métodos ... Lo que sea que funcione para usted. ¡Esta es la primera vez que tocas la clase que estás refactorizando! Las pruebas introducidas en 3 te ayudarán a refactorizar sin romper nada

Puede evitar el paso 2 si quiere hacerlo 'todo', pero este enfoque es el más puro en el sentido de que evita cambiar las clases que no tienen pruebas para verificar que no se rompe nada. Personalmente, encuentro que esto es un poco excesivo pero YMMV. La premisa básica es que avanza hacia una clase que tiene dependencias inyectadas en lugar de recuperadas de forma estática.

Además, incluso si tiene usos legítimos para un singleton, debe TODAVÍA inyectarlos. Los Singletons tratan de garantizar que solo exista una instancia de una clase determinada. El patrón clásico con una función estática accesible globalmente logra esto, pero desafortunadamente también nos aleja de inyectar esa instancia debido a un código de ejemplo malo que flota en la web. Existen muchos marcos que pueden manejar la inyección de dependencias para usted y la mayoría de ellos tendrá una forma de configurar un objeto para que la misma instancia se reutilice en toda la aplicación, lo que hace que sea un singleton.

    
respondido por el JDT 14.10.2015 - 10:44
11

El miedo a los singletons es muy exagerado. Si lo necesita de manera confiable, exactamente una de varias construcciones grandes, no hay nada de malo en tenerlas. (Si desea escribir módulos estáticos en su lugar, y el idioma no lo permite, entonces ese puede ser un problema con el idioma, no con su programa).

Un argumento común en contra de los singletons es que son difíciles de burlar para las pruebas unitarias. Pero eso solo se aplica si usted codifica su clase en su código. El patrón de singleton está realmente preocupado por asegurarse de que solo exista una instancia de una clase específica . Nadie le impide tener varias implementaciones de una interfaz de servicio, cada de las cuales es un singleton, y las intercambia / inyecta / carga dinámicamente según sea necesario para fines comerciales y de prueba.

    
respondido por el Kilian Foth 14.10.2015 - 10:42

Lea otras preguntas en las etiquetas