Blog Formação DEV

I de SOLID: Separar para Conquistar – A Arte de Segregar Interfaces

Já precisou implementar uma interface enorme, cheia de métodos que sua classe nem usa? Isso gera código inchado, difícil de entender e com responsabilidade demais para uma única classe. Com o Princípio da Segregação de Interfaces, você aprende a dividir para conquistar.
I de SOLID: Separar para Conquistar – A Arte de Segregar Interfaces
Texto de: Carlos Alexandre

Introdução

O Princípio da Segregação de Interfaces foi formulado por Robert C. Martin (Uncle Bob), um dos criadores dos princípios SOLID. Ele propõe que nenhuma classe deva ser forçada a depender de métodos que não utiliza.

Esse princípio trata diretamente de um problema comum em projetos orientados a objetos: interfaces muito grandes, que obrigam implementações a lidar com funcionalidades que não fazem sentido para elas.

A ideia central é simples:

“Clientes não devem ser forçados a depender de interfaces que não utilizam.”

Em outras palavras, quanto mais coesas e específicas forem as interfaces, mais flexível e sustentável será o seu sistema.

Se isso ainda parece teórico, não se preocupe. Ao longo deste artigo, você verá como esse princípio pode ser aplicado na prática — com exemplos reais e explicações claras para evitar armadilhas comuns ao projetar interfaces.

🔌 Interface Segregation: Separar para Conquistar

O Princípio da Segregação de Interfaces (Interface Segregation Principle — ISP) é um dos fundamentos do SOLID e foi proposto por Robert C. Martin (Uncle Bob). Ele defende que nenhuma classe deve ser forçada a depender de métodos que não utiliza.

Em outras palavras, interfaces grandes e genéricas devem ser quebradas em interfaces menores e mais específicas, para que cada classe implemente apenas os comportamentos que realmente fazem sentido para ela.

A ideia central é clara:

“Clientes não devem ser forçados a depender de interfaces que não utilizam.”

Quando esse princípio é ignorado, acabamos com classes inchadas, dependências desnecessárias e uma violação do design orientado a objetos. Isso compromete a flexibilidade, dificulta testes, e pode até criar dependências frágeis que quebram o sistema com mudanças pequenas.

❗️ Consequências de ignorar o ISP:

  • Acoplamento desnecessário: uma classe depende de métodos que não usa, ficando vulnerável a mudanças que não deveriam afetá-la.
  • Baixa coesão: interfaces que tentam fazer “de tudo” dificultam a leitura e a manutenção do código.
  • Implementações forçadas: classes precisam implementar métodos irrelevantes, levando a implementações vazias, falsas ou que lançam exceções.
  • Violações em cascata: ao modificar uma interface genérica, múltiplas classes podem ser impactadas mesmo que não tenham relação direta com a alteração.

Nos próximos tópicos, vamos explorar como aplicar o ISP, na prática, com exemplos reais e comparações entre uma má prática comum e uma estrutura adequada baseada em interfaces coesas e específicas.

❌ Exemplo de violação do Interface Segregation Principle

Imagine que estamos modelando funcionalidades de um sistema de dispositivos inteligentes. Criamos uma interface genérica para todos os dispositivos:

interface DispositivoInteligente {
  ligar(): void;
  desligar(): void;
  conectarWifi(): void;
  atualizarFirmware(): void;
} 

Agora criamos uma classe para representar uma lâmpada inteligente:

class LampadaInteligente implements DispositivoInteligente {
  ligar() {
    console.log("Lâmpada ligada");
  }

  desligar() {
    console.log("Lâmpada desligada");
  }

  conectarWifi() {
    console.log("Conectando a lâmpada ao Wi-Fi...");
  }

  atualizarFirmware() {
    throw new Error("Lâmpadas não recebem atualizações de firmware");
  }
} 

Embora a implementação “funcione”, estamos forçando a lâmpada a lidar com comportamentos que não fazem parte de sua natureza. Isso viola o ISP.

Imagine que agora criamos outro dispositivo, como uma cafeteira inteligente. Ela pode se conectar à internet, mas também não precisa atualizar firmware, e pode não ter o mesmo ciclo de liga/desliga de uma lâmpada. A interface genérica começa a atrapalhar

✅ Exemplo que respeita o Interface Segregation Principle

Vamos refatorar criando interfaces menores e mais específicas:

interface Controlavel {
  ligar(): void;
  desligar(): void;
}

interface Conectavel {
  conectarWifi(): void;
}

interface Atualizavel {
  atualizarFirmware(): void;
} 

Agora cada classe implementa apenas o que realmente faz sentido para ela:

class LampadaInteligente implements Controlavel, Conectavel {
  ligar() {
    console.log("Lâmpada ligada");
  }

  desligar() {
    console.log("Lâmpada desligada");
  }

  conectarWifi() {
    console.log("Conectando a lâmpada ao Wi-Fi...");
  }
}

class Roteador implements Controlavel, Conectavel, Atualizavel {
  ligar() {
    console.log("Roteador ligado");
  }

  desligar() {
    console.log("Roteador desligado");
  }

  conectarWifi() {
    console.log("Roteador conectado à rede");
  }

  atualizarFirmware() {
    console.log("Atualizando firmware do roteador...");
  }
} 

Com isso, cada classe é mais coesa, modular e independente. Podemos evoluir os comportamentos sem impactar classes que não têm relação com a mudança.

🤝 ISP e LSP — Princípios que se complementam

Assim como vimos no exemplo do Princípio de Liskov, segregar corretamente as interfaces ajuda a manter o contrato entre tipos e comportamentos mais previsível e seguro.

Ao criar interfaces específicas como Controlavel e Atualizavel, garantimos que nenhuma classe seja forçada a implementar métodos irrelevantes — respeitando o ISP.

E, ao mesmo tempo, evitamos situações em que uma subclasse quebra a expectativa do sistema — como quando LampadaInteligente lança erro ao tentar atualizar firmware, o que quebraria o contrato de uma interface maior — respeitando também o LSP.

➡️ Em resumo, quando respeitamos o ISP, contribuímos diretamente para cumprir o LSP, criando sistemas mais robustos, com classes e interfaces bem definidas, fáceis de entender, estender e manter.

🚨 Sinais comuns de violação do Interface Segregation Principle:

  • Interfaces com métodos demais: quando uma interface possui métodos que só fazem sentido para parte das implementações, é sinal claro de que ela está inchada.
  • Implementações que lançam erros ou deixam métodos vazios: se uma classe precisa implementar um método apenas para lançar um throw new Error("não implementado"), a interface está sendo imposta de forma inadequada.
  • Comentários explicando por que um método não é usado: quando o próprio código precisa se justificar — "esse método não é usado por essa classe" —, a segregação está sendo ignorada.
  • Alta sensibilidade a mudanças: interfaces muito genéricas causam efeito dominó: uma mudança afeta várias classes que não deveriam ser impactadas.
  • Código com instanceof ou verificações condicionais dentro de métodos implementados: Isso mostra que uma interface está sendo usada por classes com comportamentos diferentes demais para compartilhar o mesmo contrato.

💡 Dica prática:

Sempre que você se deparar com uma interface que exige implementação de muitos métodos, se pergunte:

“Essa classe realmente precisa de todos esses métodos, ou está sendo forçada a aceitar comportamentos que não são dela?”

Se a resposta for não, é hora de dividir a interface em unidades menores, respeitando o ISP e permitindo implementações mais coesas e enxutas.


Benefícios de aplicar o Interface Segregation Principle (ISP)

Quando aplicamos o ISP corretamente, nossos sistemas ganham clareza, modularidade e flexibilidade. Cada classe se torna mais focada e menos acoplada, o que facilita testes, manutenção e evolução da aplicação.

Os principais benefícios incluem:

  • Interfaces mais coesas e significativas: elas representam com clareza o comportamento esperado de quem as implementa.
  • Implementações mais simples e seguras: cada classe trata apenas dos métodos que realmente fazem parte de sua lógica.
  • Menos dependências desnecessárias: as classes não ficam vulneráveis a mudanças em métodos que não utilizam.
  • Menor complexidade no código: evita implementações forçadas e reduz a necessidade de condicionais internas desnecessárias.
  • Mais liberdade para evoluir o sistema: podemos adicionar novos comportamentos sem impactar classes que não têm relação com eles.

Quando interfaces são pequenas, bem definidas e específicas, o código se torna mais robusto e fácil de entender — respeitando um dos pilares do design orientado a objetos.

✨ Conclusão

O Princípio da Segregação de Interfaces (ISP) é essencial para manter a simplicidade, coesão e flexibilidade em sistemas orientados a objetos. Ao aplicá-lo, garantimos que cada classe implemente apenas o que realmente faz sentido para ela, sem depender de contratos genéricos e inflados.

Os resultados de seguir o ISP são claros:

  • Classes mais limpas e focadas, livres de métodos desnecessários.
  • Interfaces mais expressivas, que representam comportamentos reais do domínio.
  • Menos impacto em mudanças, com código mais estável e confiável.
  • Melhor alinhamento com o LSP, permitindo heranças e substituições mais seguras.

Neste artigo, vimos como identificar violações ao ISP, como refatorar interfaces de forma eficiente e como essa prática contribui para sistemas mais organizados e preparados para crescer de forma saudável.

Ao “separar para conquistar”, aplicamos o ISP não apenas como um princípio técnico, mas como uma filosofia de design que respeita a simplicidade e o propósito de cada componente do sistema.

Sobre o autor
Cod3r

Cod3r

Com mais de 400 mil alunos, a Cod3r é uma das principais escolas de tecnologia do País. Um de seus produtos mais importantes é a Formação DEV, com objetivo de preparar os profissionais para o mercado.

Ótimo! Inscreveu-se com sucesso.

Bem-vindo de volta! Registou-se com sucesso.

Assinou com sucesso o Blog Formação DEV .

Sucesso! Verifique o seu e-mail para obter o link mágico para se inscrever.

As suas informações de pagamento foram atualizadas.

Seu pagamento não foi atualizado.