SOLID

GRUPO 1

S: Principio de Responsabilidad Única

Cada clase o componente debería tener una única responsabilidad.

Ejemplo sin implementar Responsabilidad Única:

class ServicioUsuario
{
    public bool PagarDeudas(int userID)
    {
        var pagadas = false;
        if (HayDineroEnElBanco(userID))
        {
            pagadas = true;
        }
        return pagadas;
    }

    public bool HayDineroEnElBanco(int userID)
    {
        return true;
    }
}

Ejemplo implementando Responsabilidad Única:

class ServicioUsuario
{
    private readonly ServicioBanco _servicioBanco;

    public servicioUsuario(ServicioBanco servicioBanco)
    {
        _servicioBanco = servicioBanco;
    }

    public bool PagarDeudas(int userID)
    {
        var pagadas = false;
        if (_servicioBanco.HayDineroEnElBanco(userID))
        {
            pagadas = true;
        }
        return pagadas;
    }

}

class ServicioBanco
{
    public bool HayDineroEnElBanco(int userID)
    {
        return true;
    }
}

o: Principio de abierto/cerrado

 Las entidades de software deben estar abiertas para su extensión, pero cerradas para su modificación.

Ejemplo sin implementar Principio de abierto/cerrado

class Admin
{
    public int Id { get; set; }
    public string Name { get; set; }
}

class User
{
    public int Id { get; set; }
    public string Name { get; set; }
}

class UserFeatures
{
    public bool UserCanMakeAPayment(User user)
    {
        return true;
    }

    public bool AdminCanMakeAPayment(Admin user)
    {
        return true;
    }
}

Ejemplo implementando Principio de abierto/cerrado:

abstract class BaseUser
{
    public int Id { get; set; }
    public string Name { get; set; }
}

class Admin : BaseUser { }

class User : BaseUser { }

class UserFeatures
{
    public bool CanMakeAPayment(BaseUser user)
    {
        return true;
    }
}

L: Principio de sustitución de Liskov

Los objetos de un programa deberían ser reemplazables por instancias de sus subtipos sin alterar el correcto funcionamiento del programa.

Ejemplo sin implementar Sustitución de Liskov

public class Rectangle {
     
    private int width;
    private int height;
 
    public int getWidth() {
        return width;
    }
 
    public void setWidth(int width) {
        this.width = width;
    }
 
    public int getHeight() {
        return height;
    }
 
    public void setHeight(int height) {
        this.height = height;
    }
 
    public int calculateArea() {
        return width * height;
    }
}

public class Square extends Rectangle {
 
    @Override public void setWidth(int width) {
        super.setWidth(width);
        super.setHeight(width);
    }
 
    @Override public void setHeight(int height) {
        super.setHeight(height);
        super.setWidth(height);
    }
}
@Test
public void testArea() {
    Rectangle r = new Rectangle();
    r.setWidth(5);
    r.setHeight(4);
    assertEquals(20, r.calculateArea());
}

Ejemplo implementando sustitución de Liskov

public class Rectangle {
 
    public final int width;
    public final int height;
 
    public Rectangle(int width, int height) {
        this.width = width;
        this.height = height;
    }
}
 
public class Square extends Rectangle {
 
    public Square(int side) {
        super(side, side);
    }
}

i: Principio de segregación de la interfaz

Muchas interfaces cliente específicas son mejores que una interfaz de propósito general
 

Ejemplo sin implementar segregación de la interfaz

interface SpecialPower
{
    void FireAttack();
    void SummonAMonster();
    void TimeStop();
}

class FireMage : SpecialPower
{
    public void FireAttack()
    {
    }

    public void SummonAMonster()
    {
        throw new Exception("Can't use that");
    }

    public void TimeStop()
    {
        throw new Exception("Can't use that");
    }
}

class Summoner : SpecialPower
{
    public void FireAttack()
    {
        throw new Exception("Can't use that");
    }

    public void SummonAMonster()
    {
    }

    public void TimeStop()
    {
        throw new Exception("Can't use that");
    }
}

class GrandMage : SpecialPower
{
    public void FireAttack()
    {
    }

    public void SummonAMonster()
    {
    }

    public void TimeStop()
    {
    }
}

Ejemplo implementando segregación de la interfaz

interface IFireSpell
{
    void FireAttack();
}

interface ISummonSpell
{
    void SummonAMonster();
}

interface ITimeStopSpell
{
    void TimeStop();
}

class FireMage : IFireSpell
{
    public void FireAttack()
    {
    }
}

class Summoner : ISummonSpell
{
    public void SummonAMonster()
    {
    }
}

class GrandMage : IFireSpell, ISummonSpell, ITimeStopSpell
{
    public void FireAttack()
    {
    }

    public void SummonAMonster()
    {
    }

    public void TimeStop()
    {
    }
}

D:  Principio de inversión de la dependencia

Se debe depender de abstracciones, no depender de implementaciones

Ejemplo sin implementar inversión de dependencias

class EmailProvider1
{
    public void Send()
    {

    }
}

class EmailProvider2
{
    public void Send()
    {

    }
}

class EmailService
{
    public void SendAnEmailUsingEmailProvider1(EmailProvider1 emailProvider)
    {
        emailProvider.Send();
    }

    public void SendAnEmailUsingEmailProvider2(EmailProvider2 emailProvider)
    {
        emailProvider.Send();
    }
}

Ejemplo implementando inversión de dependencias

interface IEmailProvider
{
    void Send();
}

class EmailProvider1 : IEmailProvider
{
    public void Send()
    {

    }
}

class EmailProvider2 : IEmailProvider
{
    public void Send()
    {

    }
}

class EmailService
{
    private readonly IEmailProvider _emailProvider;

    public EmailService(IEmailProvider emailProvider)
    {
        _emailProvider = emailProvider;
    }

    public void Send()
    {
        _emailProvider.Send();
    }
}

SOLID

By Lucas Maidana

SOLID

SOLID Design principles

  • 292