Ho letto Pulisci codice e vari articoli online su SOLID ultimamente, e più ne leggo, più mi sento come se non sapessi nulla.
Diciamo che sto costruendo un'applicazione web usando ASP.NET MVC 3. Diciamo che ho un UsersController
con un'azione Create
come questa:
public class UsersController : Controller
{
public ActionResult Create(CreateUserViewModel viewModel)
{
}
}
In quel metodo di azione voglio salvare un utente nel database se i dati inseriti sono validi.
Ora, secondo il Principio di Responsabilità Unica, un oggetto dovrebbe avere una singola responsabilità e tale responsabilità dovrebbe essere interamente incapsulata dalla classe. Tutti i suoi servizi dovrebbero essere strettamente allineati a tale responsabilità. Poiché la convalida e il salvataggio nel database sono due responsabilità separate, suppongo che dovrei creare una classe separata per gestirli in questo modo:
public class UsersController : Controller
{
private ICreateUserValidator validator;
private IUserService service;
public UsersController(ICreateUserValidator validator, IUserService service)
{
this.validator = validator;
this.service= service;
}
public ActionResult Create(CreateUserViewModel viewModel)
{
ValidationResult result = validator.IsValid(viewModel);
if (result.IsValid)
{
service.CreateUser(viewModel);
return RedirectToAction("Index");
}
else
{
foreach (var errorMessage in result.ErrorMessages)
{
ModelState.AddModelError(String.Empty, errorMessage);
}
return View(viewModel);
}
}
}
Questo mi rende alcuni sensato, ma non sono affatto sicuro che questo sia il modo giusto per gestire cose come questa. Ad esempio, è completamente possibile passare un'istanza non valida di CreateUserViewModel
alla classe IUserService
. So che potrei usare le NoteAnnotations integrate, ma cosa succede quando non sono sufficienti? Immagine che il mio ICreateUserValidator
controlla il database per vedere se esiste già un altro utente con lo stesso nome ...
Un'altra opzione è lasciare che IUserService
si prenda cura della convalida in questo modo:
public class UserService : IUserService
{
private ICreateUserValidator validator;
public UserService(ICreateUserValidator validator)
{
this.validator = validator;
}
public ValidationResult CreateUser(CreateUserViewModel viewModel)
{
var result = validator.IsValid(viewModel);
if (result.IsValid)
{
// Save the user
}
return result;
}
}
Ma sento che sto violando il Principio di Responsabilità Unica qui.
Come devo comportarmi con qualcosa del genere?