DEV Community

Cover image for PRINCÍPIO DA SUBSTITUIÇÃO DE LISKOV
Victor Lis Bronzo
Victor Lis Bronzo

Posted on

PRINCÍPIO DA SUBSTITUIÇÃO DE LISKOV

Uma classe mãe deve ser capaz de ser substituída pelas suas classes filhas sem que a aplicação quebre.

Isso na prática ajuda a organizar a ideia de herança, já que nos faz evitar estender uma classe mãe, apenas para depois remover um método já implementado ou fazer um “throw new Error(‘Not implemented’)”.

Fazendo com que tenhamos mais cuidado no planejamento.


O MAIOR SINTOMA DE ERRO

Infelizmente é um sintoma que aparece de forma tardia, mas é justamente quando vamos fazer uma nova implementação.

Você percebe que feriu o Liskov quando você vai construir uma classe ou subclasse e precisa lançar um erro proposital na implementação de um método.

Justamente porque aquele método não deveria estar ali, mas está.


UM EXEMPLO RUIM

Por exemplo em um sistema de entregas.

Nesse caso a classe “Delivery” deveria ser a mãe/base para as demais implementações.

Mas a classe ‘MotoboyDelivery’ quebra isso.

Exemplo de Código:

// RUIM: A subclasse quebra o contrato da classe mãe.
class Delivery {
  public calculateShipping(): number {
    return 15.0;
  }

  public getTrackingCode(): string {
    return "TRK123456789";
  }
}

class MotoboyDelivery extends Delivery {
  public calculateShipping(): number {
    return 8.0;
  }

  // ERRO! Não tem código de rastreio.
  public getTrackingCode(): string {
    throw new Error("Motoboys não possuem código.");
  }
}
Enter fullscreen mode Exit fullscreen mode

A SOLUÇÃO

Para quem ainda não conhece o 'Liskov Substitution Principle', pode parecer que encaixar uma sequência de ifs é a solução.

Mas na verdade o caminho ideal é repensar como essa abstração é construída.

Um bom norte é pensar que uma classe filha sempre deve ser capaz de substituir o lugar da mãe, sem quebrar a aplicação.


UM EXEMPLO BOM

Ainda no sistema de entregas.

‘Delivery’ agora tem no meio do caminho ‘TrackableDelivery’.

Com isso, cada “folha”/ponta da aplicação herda quem faz mais sentido e nada é quebrado.

Exemplo de Código:

interface Delivery {
  calculateShipping(): number;
}

interface TrackableDelivery extends Delivery {
  getTrackingCode(): string;
}

class CorreiosDelivery implements TrackableDelivery {
  public calculateShipping(): number {
    return 15.0;
  }

  public getTrackingCode(): string {
    return "BR987654321X";
  }
}

class MotoboyDelivery implements Delivery {
  public calculateShipping(): number {
    return 8.0;
  }
}
Enter fullscreen mode Exit fullscreen mode

CONCLUSÃO

Respeitar o Liskov garante previsibilidade.

Quem chamar o seu método confia cegamente que o contrato será cumprido, independente da classe que for passada por debaixo dos panos.

Isso traz mais segurança durante a implementação de novas features ou mesmo na sustentação das antigas.


Meus Links
Github: victor-lis-bronzo
Linkedin: victor-lis-bronzo
Portfólio: portfolio.victorlisbronzo.me
Portfólio mais legal: victorlisbronzo.me


Deixe sua reação ❤️
E você já se deparou com um método ferindo Liskov em alguma aplicação?

Top comments (0)