Supponiamo di avere un elenco di entità Task e un ProjectTask
sottotipo. Le attività possono essere chiuse in qualsiasi momento, tranne ProjectTasks
che non possono essere chiuse una volta che hanno lo stato Avviato. L'interfaccia utente dovrebbe garantire che l'opzione per chiudere un avvio ProjectTask
non sia mai disponibile, ma nel dominio sono presenti alcune garanzie:
public class Task
{
public Status Status { get; set; }
public virtual void Close()
{
Status = Status.Closed;
}
}
public class ProjectTask : Task
{
public override void Close()
{
if (Status == Status.Started)
throw new Exception("Cannot close a started Project Task");
base.Close();
}
}
Ora quando si chiama Close()
un'attività, è possibile che la chiamata fallisca se è ProjectTask
con lo stato avviato, quando non sarebbe se fosse un'attività base. Ma questi sono i requisiti aziendali. Dovrebbe fallire. Questo può essere considerato una violazione del principio di sostituzione di Liskov ?
public Status Status { get; private set; }
:; altrimenti il Close()
metodo può essere aggirato.
Task
non introducano bizzarre incompatibilità nel codice polimorfico di cui è a conoscenza Task
è un grosso problema. LSP non è un capriccio, ma è stato introdotto proprio per aiutare la manutenibilità nei sistemi di grandi dimensioni.
TaskCloser
processo che closesAllTasks(tasks)
. Questo processo ovviamente non tenta di catturare eccezioni; dopo tutto, non fa parte del contratto esplicito di Task.Close()
. Ora introduci ProjectTask
e improvvisamente TaskCloser
inizi a lanciare (forse non gestite) eccezioni. Questo è un grosso problema!