static - injection - IOC-¿Se deberían conectar las clases de util con métodos de ayuda estática con IOC?
inversion of control vs dependency injection (4)
Solo trato de entender los principios de la COI.
P1: Métodos estáticos : ¿deberían las clases de uso con métodos de ayuda estática estar conectados con IOC?
Por ejemplo, si tengo una clase HttpUtils con varios métodos estáticos, ¿debería intentar pasarla a otras clases de lógica de negocios a través de IOC?
Seguir las preguntas para esto podría ser:
P2: Singletons - ¿Qué pasa con las cosas como el registro en el que normalmente puede obtener acceso a través de una llamada de tipo Logger.getInstance ()? ¿Normalmente dejaría esto como está y NO usaría IOC para inyectar el registrador en las clases de negocios que lo necesitan?
P3: Clases estáticas: realmente no he usado este concepto, pero hay algunas pautas sobre cómo manejaría esto normalmente si se estuviera moviendo hacia un enfoque basado en IOC.
Gracias por adelantado.
El dilema surge cuando las clases de utilidad, por ejemplo, necesitan acceso a la base de datos. Si bien db accessor necesita Ioc, la clase de utilidad tiene que usar Ioc como, por lo que no puede ser estática.
Pero realmente quiero que la clase de utilidad sea estática, tan fácil de consumir. No quiero rellenar el constructor de cada clase de consumo que necesita clases de utilidad.
Consumir clases en sí mismo puede que ni siquiera necesiten acceso a la base de datos. Así que no quiero inyectar db accessor y pasarlo a clases de utilidades también.
Supongo que no hay una solución perfecta por ahora. Un día, espero que vayamos un paso más allá, además de la inyección de constructor / propiedad, hay una "configuración / inyección de contexto global", o "inyección estática", que aplica Ioc más allá de la creación de objetos.
Piensa, ¿por qué no?
Lo curioso de la IoC es que los objetos escritos en el estilo generalmente se desacoplan de esos detalles.
Usemos la clase de utilidad como ejemplo:
public class HttpUtils
{
public static void DoStuff(int someValue)
{
// ...
}
}
En una aplicación no enfocada en IoC, puede usar ese método directamente:
public class Foo
{
public int Value { get; set; }
public void DoStuff()
{
HttpUtils.DoStuff(Value);
}
}
Sin embargo, eso DoStuff
la definición de DoStuff
directamente con su implementación. IoC se esfuerza por divorciarse de ese tipo de detalles, por lo que en su lugar definimos la operación por sí sola:
public interface IDoesStuff
{
void DoStuff(int someValue);
}
Luego, dejamos espacio en Foo
para que la implementación cambie:
public class Foo
{
private readonly IDoesStuff _doesStuff;
public Foo(IDoesStuff doesStuff)
{
_doesStuff = doesStuff;
}
public int Value { get; set; }
public void DoStuff()
{
_doesStuff.DoStuff(Value);
}
}
Esto desacopla a Foo
de HttpUtils
. El implementador del concepto de DoStuff
ahora es un detalle de configuración y no una dependencia inherente (como lo es con el método estático).
Tenga en cuenta que Foo
no tiene idea de si su IDoesStuff
es un singleton o no. Esa vida útil también es un detalle de configuración, y no un detalle inherente de Foo
.
En resumen, IoC y static
están generalmente en desacuerdo, ya que IoC promueve el cambio y la static
, por definición, lo evita. Declare sus dependencias en sus constructores y casi nunca verá que usa static
funcionalidad static
.
Los métodos estáticos por definición no necesitan una instancia. DI / IOC tiene como objetivo satisfacer interfaces con clases concretas y dado que su clase estática junto con sus métodos estáticos, por definición, no pueden implementar una interfaz o extender una clase, la pregunta no tiene sentido. No tiene sentido pasar la clase auxiliar porque uno no necesita la instancia para usar los métodos estáticos. Su código siempre ejecutará los mismos métodos auxiliares estáticos, incluso sin una instancia.
En una aplicación potenciada por IOC / DI, uno definiría interfaces y tendría al menos una implementación. Se trata de gestionar instancias y sus dependencias.
Un contenedor IoC suele ser útil para inyectar objetos que tienen estado; o clases o interfaces que tienen más de una implementación, incluso si la segunda implementación es un simulacro para propósitos de prueba. Si ninguno de estos es cierto, no ganas nada inyectándolo. el lenguaje más común en estos días es tener a su clase al frente de una interfaz que la implementación real y simulada pueda implementar.
1) Métodos estáticos en clases de ayuda : no, IoC no los inyecta a menudo. Típicamente son utilidades sin estado.
Para usar un ejemplo muy simple, no necesita dos versiones de un método de utilidad llamado StringUtils.Reverse()
. Solo necesita uno, y puede escribir pruebas a su alrededor fácilmente porque no tiene estado ni dependencias, por lo que no hay absolutamente ningún beneficio en burlarse de él. Ejemplo de prueba:
string reversedString = StringUtils.Reverse("input");
Assert.AreEqual("tupni", reversedString)
Si la utilidad no es realmente sin estado (por ejemplo, depende de HttpContext.Current), entonces debe hacer que la dependencia sea explícita inyectándola y no haciendo que la utilidad sea estática.
2) Singletons : a menudo sí, se inyectan singletons. Pero algo bueno de IoC es que te preocupas menos por si solo hay uno de algo o no. Ganas flexibilidad en la creación de instancias utilizando IoC. La decisión de tener un tipo particular como instancia única o nueva cada vez se convierte en parte de la configuración del contenedor IoC y nada más en el código debe cambiar.
Así que singleton-hood deja de ser una preocupación separada que debe ser codificada en la clase (y las clases que tienen múltiples preocupaciones cuando no tienen que hacerlo es mala), y se convierte en la preocupación del contenedor IoC. No codificas la clase "como un singleton" con nada especial como un constructor privado y un método public static GetInstance()
, simplemente lo codificas para la preocupación principal, mientras que la configuración del contenedor IoC especifica si es un singleton o no, o en algún punto intermedio, como una instancia por hilo.
3) Clases estáticas : son el hogar natural de los métodos estáticos. Considere hacer los métodos de extensión de métodos estáticos cuando sea apropiado. No puedes inyectar estas clases, ya que no puedes crearlas. El uso de clases estáticas hace que el código de procedimiento no orientado a objetos. Esto no es algo malo para los pequeños métodos de ayuda, pero si la mayoría del código es así, entonces no está utilizando las potentes funciones OO de la plataforma .Net.