Esta pregunta es el resultado de un mensaje por Jeffery Palermo el código Cómo moverse ramificada y de inyección de dependencias http://jeffreypalermo.com/blog/constructor-over-injection-anti-pattern/COI y constructor de sobre-inyección resolución anti-patrón
En su puesto, Jeffery tiene una clase (public class OrderProcessor : IOrderProcessor
) que toma 2 interfaces en el constructor. Uno es un validador IOrderValidator
y una interfaz IOrderShipper
. Su código de método se bifurca después de usar solo métodos en la interfaz IOrderValidator
y nunca usa nada en la interfaz IOrderShipper
.
Sugiere crear una fábrica que llame a un método estático para obtener el delegado de la interfaz. Él está creando un nuevo objeto en su código refactorizado que parece innecesario.
Supongo que el quid de la cuestión es que estamos utilizando IoC para construir todos nuestros objetos, independientemente de si se están utilizando o no. Si instancia un objeto con 2 interfaces y tiene un código que podría bifurcarse para no usar uno de ellos, ¿cómo lo maneja?
En este ejemplo, suponemos _validator.Validate(order)
siempre devuelve falso y el método IOrderShipper.Ship()
nunca es llamado.
Código original:
public class OrderProcessor : IOrderProcessor
{
private readonly IOrderValidator _validator;
private readonly IOrderShipper _shipper;
public OrderProcessor(IOrderValidator validator, IOrderShipper shipper)
{
_validator = validator;
_shipper = shipper;
}
public SuccessResult Process(Order order)
{
bool isValid = _validator.Validate(order);
if (isValid)
{
_shipper.Ship(order);
}
return CreateStatus(isValid);
}
private SuccessResult CreateStatus(bool isValid)
{
return isValid ? SuccessResult.Success : SuccessResult.Failed;
}
}
public class OrderShipper : IOrderShipper
{
public OrderShipper()
{
Thread.Sleep(TimeSpan.FromMilliseconds(777));
}
public void Ship(Order order)
{
//ship the order
}
}
Código refactorizado
public class OrderProcessor : IOrderProcessor
{
private readonly IOrderValidator _validator;
public OrderProcessor(IOrderValidator validator)
{
_validator = validator;
}
public SuccessResult Process(Order order)
{
bool isValid = _validator.Validate(order);
if (isValid)
{
IOrderShipper shipper = new OrderShipperFactory().GetDefault();
shipper.Ship(order);
}
return CreateStatus(isValid);
}
private SuccessResult CreateStatus(bool isValid)
{
return isValid ? SuccessResult.Success : SuccessResult.Failed;
}
}
public class OrderShipperFactory
{
public static Func<IOrderShipper> CreationClosure;
public IOrderShipper GetDefault()
{
return CreationClosure(); //executes closure
}
}
Y aquí es el método que configura esta fábrica en el momento de puesta en marcha (Global.asax para ASP.NET):
private static void ConfigureFactories()
{
OrderShipperFactory.CreationClosure =
() => ObjectFactory.GetInstance<IOrderShipper>();
}
presumiblemente, el código refactorizado no debe tomar el IOrderShipper en el constructor ... de lo contrario, ¿cuál es el sentido de la refactorización? –
En la publicación que enlazó, su código refactorizado no tomó un IOrderShipper en el constructor, pero en su código refactorizado sí lo hace. No necesariamente estoy de acuerdo con Jeffrey Pallermo en este caso, pero es una distinción importante entre su implementación y la suya. –
Supongo que he copiado el código incorrectamente. Pensé que sería más fácil ponerlo todo aquí = (Corregido –