DEV Community

Yuri Peixinho
Yuri Peixinho

Posted on

ISP — Interface Segregation Principle (Princípio da Segregação de Interface)

Interface Segregation Principle

O ISP afirma que uma interface não deve forçar a classe a implementar métodos que elas não utilizam. A ideia é quebras grandes interfaces em menores e mais específicas, ou seja, em vez de interfaces gigantes e genéricas (”interfaces gordas”), devemos ter “interfaces magras”, quebradas e mais específicas.

“Clientes não devem ser forçados a depender de métodos que não usam.”

Pense nisso como um menu de restaurante:

  • Violação do ISP: O restaurante obriga você a comprar o combo com hambúrguer, batata, refrigerante, sorvete e café, mesmo que você só queira o hambúrguer
  • Aplicação do ISP: O menu é segregado. Você pode pedir itens individuais ou combos menores que façam sentido para o seu "apetite" (necessidade)

Exemplo didático do problema

Imagine que temos a Interface chamada ITrabalhador, ela possui métodos como Codificar(), Testar() e GerenciarProjetos().

  1. Você vai criar uma classe chamada Programador que implementa essa interface. Até esse cenário tudo ocorre como o esperado.
  2. O problema é que se você criar uma classe Gerente, e implementar a mesma interface ela será obrigada a implementar Codificar(), mesmo que o gerente não escreva código.

Essa prática cria um acoplamento desnecessário e “polui” o código com métodos vazios ou que lançam exceções como throw new NotImplementedException.

Exemplo técnico do problema

Vamos retomar o exemplo acima e desenvolver com o código com C# de duas formas, uma que viola o ISP e outra que não viola.

1. Violação estrutural

using System;

// Uma "Interface Gorda" que tenta fazer tudo
public interface ITrabalhador
{
    void Codificar();
    void Testar();
    void GerenciarProjeto();
}

public class Programador : ITrabalhador
{
    public void Codificar() => Console.WriteLine("Escrevendo código C#...");
    public void Testar() => Console.WriteLine("Testando bugs...");
    public void GerenciarProjeto() => Console.WriteLine("Atualizando o JIRA..."); 
    // Ok, talvez o programador faça um pouco de tudo.
}

public class Gerente : ITrabalhador
{
    public void Codificar()
    {
        // Oxente! O Gerente não deveria ser obrigado a ter este método.
        throw new NotImplementedException("Gerentes não codificam!");
    }

    public void Testar()
    {
        throw new NotImplementedException("Gerentes não testam!");
    }

    public void GerenciarProjeto() => Console.WriteLine("Gerenciando o time...");
}
Enter fullscreen mode Exit fullscreen mode

2. O Jeito Correto

Agora, vamos segregar (separar) as interfaces. Assim, cada classe só assina o "contrato" que realmente consegue cumprir.

// Interfaces segregadas e específicas (Interfaces Magras)
public interface ICodificador
{
    void Codificar();
}

public interface ITestador
{
    void Testar();
}

public interface IGerente
{
    void GerenciarProjeto();
}

// O Programador implementa apenas o que faz sentido para ele
// Ele pode implementar múltiplas interfaces se necessário!
public class Programador : ICodificador, ITestador
{
    public void Codificar() => Console.WriteLine("Escrevendo código C#...");
    public void Testar() => Console.WriteLine("Testando bugs...");
}

// O Gerente agora está limpo e focado
public class Gerente : IGerente
{
    public void GerenciarProjeto() => Console.WriteLine("Gerenciando o time...");
}
Enter fullscreen mode Exit fullscreen mode

Top comments (0)