Attualmente ho 3 classi di servizio, tutte hanno un modello simile e ho bisogno di creare una quarta classe di servizio che amalgami la funzionalità degli altri tre.
Tre classi attuali
public class PersonService : IPersonService
{
public PersonServiceResult CreatePerson(CreatePersonParams createPersonParams)
{
using (var unitOfWork = _unitOfWorkFactory.Create())
{
// [code]
unitOfWork.Commit();
return new PersonServiceResult(...);
}
}
}
public class OrderService : IOrderService
{
public OrderServiceResult CreateOrder(
int personId,
IEnumerable<PurchaseItem> items)
{
using (var unitOfWork = _unitOfWorkFactory.Create())
{
// [code]
unitOfWork.Commit();
return new OrderServiceResult(...);
}
}
}
public class PaymentProcessingService : IPaymentProcessingService
{
public PaymentResult ProcessPayment(int orderId, CreditCard creditCard)
{
using (var unitOfWork = _unitOfWorkFactory.Create())
{
// [code]
unitOfWork.Commit();
return new PaymentResult(...);
}
}
}
Ora ho bisogno di usare il comportamento in tutte e 3 queste classi in una unità di lavoro , ho ancora bisogno che siano presenti le altre 3 classi per altre dipendenze nel progetto.
Il mio primo pensiero sarebbe quello di estrarre una classe per ciascuno dei 3 servizi che prende come argomento una unità di lavoro.
Estrazione del comportamento dalle classi correnti
public class PersonCreator
{
public CreatePersonResult CreatePerson(
IUnitOfWork unitOfWork,
CreatePersonParams createPerson)
{
// [code]
}
}
public class PersonService : IPersonService
{
private readonly PersonCreator Creator = new PersonCreator();
public PersonServiceResult CreatePerson(CreatePersonParams createPersonParams)
{
using (var unitOfWork = _unitOfWorkFactory.Create())
{
var result = Creator.CreatePerson(unitOfWork, createPersonParams);
unitOfWork.Commit();
return new PersonServiceResult(result);
}
}
}
Proposta nuova classe utilizzando il comportamento estratto
public class QuickOrderService : IQuickOrderService
{
private readonly PersonCreator PersonCreator = new PersonCreator();
private readonly OrderCreator OrderCreator = new OrderCreator();
private readonly PaymentProcessor PaymentProcessor = new PaymentProcessor();
public QuickOrderResult CreateQuickOrder(
CreatePersonParams createPersonParams,
IEnumerable<PurchaseItem> items,
CreditCard creditCard)
{
using (var unitOfWork = _unitOfWorkFactory.Create())
{
var person = PersonCreator.CreatePerson(unitOfWork, createPersonParams);
var order = OrderCreator.CreateOrder(unitOfWork, person.Id, items);
var payment = PaymentProcessor.Process(unitOfWork, order.Id, creditCard);
unitOfWork.Commit();
return QuickOrderResult(...);
}
}
}
Funziona bene, ma sono preoccupato di testare questa nuova classe.
Domande sulla proposta
- Duplica la maggior parte dei test per la classe
QuickOrderService
- Non testare questa classe poiché la maggior parte di essa è coperta da altri test
- Inietti
PersonCreator
,OrderCreator
ePaymentProcessor
inQuickOrderService
invece di installarli e provare solo cheQuickOrderService
chiama correttamente le dipendenze
Anche se facendo tutto questo excersise mi viene in mente che potrebbe esserci una soluzione migliore che riduce la duplicazione mantenendo la copertura del codice.