Primeros pasos con principios sólidos

Principio de sustitución de Liskov


Por qué usar LSP

Escenario: Supongamos que tenemos 3 bases de datos (Clientes Hipotecarios, Clientes de Cuentas Corrientes y Clientes de Cuentas de Ahorro) que brindan datos de clientes y necesitamos detalles de clientes para el apellido del cliente dado. Ahora podemos obtener más de 1 detalle de cliente de esas 3 bases de datos contra el apellido dado.


Implementación

CAPA DEL MODELO DE NEGOCIO:

public class Customer
{
    // customer detail properties...
}

CAPA DE ACCESO A DATOS:

public interface IDataAccess
{
    Customer GetDetails(string lastName);
}

La interfaz anterior está implementada por la clase abstracta

public abstract class BaseDataAccess : IDataAccess
{
    /// <summary> Enterprise library data block Database object. </summary>
    public Database Database;    
    public Customer GetDetails(string lastName)
    {
        // use the database object to call the stored procedure to retirve the customer detials
    }
}

Esta clase abstracta tiene un método común “GetDetails” para las 3 bases de datos que se extiende por cada una de las clases de base de datos como se muestra a continuación

ACCESO A DATOS DEL CLIENTE HIPOTECA:

public class MortgageCustomerDataAccess : BaseDataAccess
{
    public MortgageCustomerDataAccess(IDatabaseFactory factory)
    {
        this.Database = factory.GetMortgageCustomerDatabase();
    }
}

CUENTA CORRIENTE ACCESO A DATOS DEL CLIENTE:

public class CurrentAccountCustomerDataAccess : BaseDataAccess
{
    public CurrentAccountCustomerDataAccess(IDatabaseFactory factory)
    {
        this.Database = factory.GetCurrentAccountCustomerDatabase();
    }
}

CUENTA DE AHORRO ACCESO A DATOS DEL CLIENTE:

public class SavingsAccountCustomerDataAccess : BaseDataAccess
{
    public SavingsAccountCustomerDataAccess(IDatabaseFactory factory)
    {
        this.Database = factory.GetSavingsAccountCustomerDatabase();
    }
}

Una vez que se establecen estas 3 clases de acceso a datos, ahora dirigimos nuestra atención al cliente. En la capa Business tenemos la clase CustomerServiceManager que devuelve los detalles del cliente a sus clientes.


CAPA DE NEGOCIOS:

public class CustomerServiceManager : ICustomerServiceManager, BaseServiceManager
{
   public IEnumerable<Customer> GetCustomerDetails(string lastName)
   {
        IEnumerable<IDataAccess> dataAccess = new List<IDataAccess>()
        {
            new MortgageCustomerDataAccess(new DatabaseFactory()), 
            new CurrentAccountCustomerDataAccess(new DatabaseFactory()),
            new SavingsAccountCustomerDataAccess(new DatabaseFactory())
        };

        IList<Customer> customers = new List<Customer>();

       foreach (IDataAccess nextDataAccess in dataAccess)
       {
            Customer customerDetail = nextDataAccess.GetDetails(lastName);
            customers.Add(customerDetail);
       }

        return customers;
   }
}

No he mostrado la Inyección de Dependencia para mantenerlo simple, ya que ahora se está complicando.

Ahora, si tenemos una nueva base de datos de detalles de clientes, simplemente podemos agregar una nueva clase que amplíe BaseDataAccess y proporcione su objeto de base de datos.

Por supuesto, necesitamos procedimientos almacenados idénticos en todas las bases de datos participantes.

Por último, el cliente de CustomerServiceManagerclass solo llamará al método GetCustomerDetails, pasará el apellido y no debería preocuparse por cómo y de dónde provienen los datos.

Espero que esto le brinde un enfoque práctico para comprender LSP.

Instalación o configuración

Puede usar cualquier lenguaje IDE y OOP para implementar Principios S.O.L.I.D. En el código de ejemplo, he usado C#, ya que es el lenguaje más utilizado en .NET Word y se parece mucho a Java y C++.