Otros han explicado muy bien el problema de los singleton en general. Solo me gustaría agregar una nota sobre el caso específico de Logger. Estoy de acuerdo con usted en que generalmente no es un problema acceder a un registrador (o al registrador raíz, para ser precisos) como singleton, a través de un método estático getInstance()
o getRootLogger()
. (a menos que desee ver lo que registra la clase que está probando, pero en mi experiencia, apenas puedo recordar casos en los que esto fue necesario. Por otra parte, para otros, esto podría ser una preocupación más urgente).
En mi opinión, un registrador singleton no es una preocupación, ya que no contiene ningún estado relevante para la clase que está probando. Es decir, el estado del registrador (y sus posibles cambios) no tienen ningún efecto sobre el estado de la clase probada. Por lo tanto, no dificulta las pruebas unitarias.
La alternativa sería inyectar el registrador a través del constructor en (casi) todas las clases de su aplicación. Para la coherencia de las interfaces, debe inyectarse incluso si la clase en cuestión no registra nada en este momento; la alternativa sería que cuando descubra en algún momento que ahora necesita registrar algo de esta clase, necesita un registrador, por lo tanto necesita agregar un parámetro de constructor para DI, rompiendo todo el código del cliente. No me gustan estas dos opciones, y siento que usar DI para el registro sería simplemente complicar mi vida para cumplir con una regla teórica, sin ningún beneficio concreto.
Entonces, mi conclusión es: una clase que se usa (casi) universalmente, pero que no contiene un estado relevante para su aplicación, se puede implementar de manera segura como Singleton .