Digamos que tenemos una lista de entidades de tareas y un ProjectTask
subtipo. Las tareas se pueden cerrar en cualquier momento, excepto ProjectTasks
que no se pueden cerrar una vez que tienen el estado de Iniciado. La interfaz de usuario debe garantizar que la opción de cerrar un inicio ProjectTask
nunca esté disponible, pero existen algunas salvaguardas en el dominio:
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();
}
}
Ahora, cuando se llama Close()
a una Tarea, existe la posibilidad de que la llamada falle si es ProjectTask
con el estado iniciado, cuando no lo sería si fuera una Tarea base. Pero estos son los requisitos comerciales. Debería fallar. ¿Se puede considerar esto como una violación del principio de sustitución de Liskov ?
public Status Status { get; private set; }
:; de lo contrario, el Close()
método se puede solucionar.
Task
no introduzcan incompatibilidades extrañas en el código polimórfico que solo conoce Task
es un gran problema. LSP no es un capricho, pero se introdujo precisamente para ayudar a la mantenibilidad en sistemas grandes.
TaskCloser
proceso que closesAllTasks(tasks)
. Este proceso obviamente no intenta atrapar excepciones; después de todo, no es parte del contrato explícito de Task.Close()
. Ahora presentas ProjectTask
y de repente TaskCloser
comienzas a lanzar excepciones (posiblemente no manejadas). ¡Este es un gran problema!