Recentemente ho dato il consiglio di refactoring del codice sulla falsariga di
class Validator<T> : IValidator
{
public ValidationResult Validate(Validatable thingToValidate)
{
if(typeof(T).Name == nameof(FooThing))
{
ValidateFoo(thingToValidate);
}
if(typeof(T).Name == nameof(BarThing))
{
ValidateBar(thingToValidate);
}
if(typeof(T).Name == nameof(QuxThing))
{
ValidateQux(thingToValidate);
}
}
}
in qualcosa di simile
class Validator<T> : IValidator
{
Dictionary<string, IValidator> specificValidators; // may be injected
public ValidationResult Validate(Validatable thingToValidate)
{
var specificValidator = GetValidatorFor(typeof(T).Name);
return specificValidator.Validate(thingToValidate);
}
private IValidator GetValidatorFor(string name)
{
return specificValidators[name];
}
}
Mentre tendo a sostenere che questo uso di generici è un uso improprio, ho cercato intenzionalmente di mantenere intatta l'interfaccia pubblica.
Il fondamento logico del refactoring del codice originale era che era piuttosto rigido e aveva troppe responsabilità (alla fine della giornata, la classe era responsabile della validazione di Foo-things, Bar-things e Qux-things). Più specificamente ho sostenuto che
- L'OCP è stato danneggiato, dal momento che non è in grado di estendere la classe senza cambiarla
- L'SRP è stato danneggiato per i motivi sopra indicati
Mentre penso che questi argomenti valgano per mantenere la classe mantenibile (se fosse stato aggiunto un solo caso di validazione, la modifica non avrebbe avuto un grande impatto, ma se fossero stati altri dieci casi, la classe avrebbe davvero ottenuto ingombrante, inoltre, l'aggiunta manuale dei casi è soggetta a errori), ma sicuramente quest'ultima versione è decisamente meno leggibile.
Ammetto che non sono sicuro se si tratta di sovrastrutture eccessive o se questo refactoring è valido e richiesto per mantenere un'elevata manutenibilità. È?