ISP — o que é, princípio de segregação de interfaces no desenvolvimento

Autor: IT Sectr Publicado: 2026-05-12 Tempo de leitura: 9 min

ISP (Interface Segregation Principle) é o quarto princípio SOLID, que afirma: os clientes não devem depender de métodos que não utilizam. O princípio foi formulado por Robert Martin no contexto de design de interfaces para sistemas orientados a objetos. Conforme descrito no livro Clean Architecture (2017), o princípio de segregação de interfaces exige criar interfaces estreitamente especializadas em vez de uma única universal, o que reduz o acoplamento e simplifica a realização de alterações.

Principais pontos

  • ISP — princípio de segregação de interfaces, o quarto em SOLID
  • Clientes não devem depender de métodos que não invocam
  • Interfaces gordas (Fat Interfaces) contêm métodos irrelevantes para alguns clientes
  • Dividir interfaces reduz o acoplamento e melhora a reutilização de código
  • ISP está intimamente relacionado com SRP e Responsabilidade Única ao nível de interfaces

O que é ISP (Interface Segregation Principle)?

ISP (Interface Segregation Principle) é o princípio de segregação de interfaces que proíbe criar interfaces “gordas” com métodos não utilizados por todos os clientes. Em vez de uma interface com uma dúzia de métodos, várias interfaces pequenas são projetadas, cada uma para o seu grupo de clientes.

O princípio foi introduzido por Robert Martin como solução para o problema da “poluição de interfaces”, quando uma classe é forçada a implementar métodos de que não precisa apenas porque estão declarados numa interface comum. Em linguagens estaticamente tipadas, isso resulta em implementações vazias ou lançamento de exceções — um sinal direto de violação de ISP.

ISP e SRP complementam-se: SRP trata da responsabilidade da classe, ISP trata dos contratos de interfaces. SRP diz “uma classe — uma razão para mudar”, ISP diz “uma interface — um cenário de cliente”. Juntos formam uma arquitetura modular onde cada elemento do sistema tem limites claros.

Interfaces gordas e suas consequências

Fat Interface — uma interface que contém mais métodos do que um cliente específico necessita. Por exemplo, uma interface Worker com métodos work, eat, sleep. Um robô trabalhador não deveria implementar eat e sleep, mas é forçado a fazê-lo. A solução é dividir em Workable, Eatable, Sleepable. Cada cliente obtém exatamente o que precisa.

No desenvolvimento móvel, as interfaces gordas encontram-se em protocolos delegados e DataSource. Um protocolo pode conter métodos para dois cenários diferentes (edição + visualização), embora um ecrã específico use apenas um deles.

Como funciona o princípio de segregação de interfaces

Implementar ISP começa com a análise dos clientes de cada interface. Se dois clientes usam diferentes conjuntos de métodos de uma mesma interface — a interface deve ser dividida. Cada nova interface agrupa métodos que são invocados juntos dentro de um mesmo cenário.

O mecanismo de divisão: a interface original é dividida em várias estreitas, cada uma herdando a parte comum (se houver). Os clientes passam a depender da interface estreita necessária em vez da geral. As classes que implementam a interface original agora implementam apenas as interfaces estreitas de que realmente precisam.

Um esclarecimento importante: o grau de divisão é determinado pela quantidade de clientes e seus cenários. ISP não exige a máxima divisão (micro-interfaces com um método cada). Isso levaria a uma complexidade excessiva. O objetivo é eliminar a dependência dos clientes de métodos desnecessários, não minimizar o tamanho de cada interface.

Sinais de violação de ISP

Os principais sinais de violação de ISP incluem: classes que implementam uma interface com métodos vazios (implementação fictícia), lançamento de UnsupportedOperationException em implementações, um grande número de parâmetros ou tipos de retorno que alguns clientes não usam, e alterações frequentes na interface que afetam apenas alguns clientes.

No desenvolvimento Android, um exemplo típico de violação de ISP é a interface OnItemClickListener, que inclui métodos para clique, clique longo e deslize. Se um ecrã específico usa apenas clique — os métodos restantes ficam vazios. A solução é dividir em OnItemClickListener, OnItemLongClickListener, OnItemSwipeListener.

No desenvolvimento iOS, a violação de ISP manifesta-se nos delegados UIKit: um protocolo contém métodos para diferentes estados do componente. UITableViewDelegate inclui métodos para visualização, seleção, edição e ação de deslize. Os programadores frequentemente implementam o protocolo completo com uma dúzia de métodos vazios. Dividir em vários protocolos por grupos de responsabilidade resolve o problema.

Dependência de métodos não utilizados

O problema não é apenas estético. Quando uma interface muda (um novo método é adicionado), todas as classes que a implementam devem ser atualizadas — mesmo aquelas que não precisam do novo método. No desenvolvimento móvel com dezenas de ecrãs, isso causa alterações em cascata. ISP isola cada cliente de alterações que não lhe dizem respeito.

A violação implícita de ISP ocorre através de parâmetros de configuração. Se um método aceita um objeto com muitos campos e o cliente usa apenas 2-3 deles — é um sinal para dividir. Alternativa: vários métodos especializados com um conjunto mínimo de parâmetros.

No desenvolvimento Android, ISP é violado ao usar um único SharedPreferencesManager para ler e escrever todas as configurações da aplicação. Um Fragment que só precisa ler o tema obtém uma dependência de um gestor global com uma dúzia de métodos para diferentes tipos de dados. Dividir em ThemePreferenceProvider, AuthPreferenceProvider, FeatureFlagProvider — aplicar ISP ao nível de serviços de configuração. Cada fornecedor contém exatamente os métodos de que os seus clientes precisam.

Exemplos de ISP em aplicações móveis

Consideremos um exemplo Android com uma interface para trabalhar com dados. Violação de ISP: uma interface para todas as operações CRUD, embora nem todos os clientes precisem de todas as operações.

kotlin
// Violação de ISP: interface gorda
interface UserRepository {
    fun getAll(): List<User>
    fun getById(id: Int): User
    fun save(user: User)
    fun delete(id: Int)
}

// Após aplicar ISP: interfaces estreitas
interface UserReader {
    fun getAll(): List<User>
    fun getById(id: Int): User
}

interface UserWriter {
    fun save(user: User)
    fun delete(id: Int)
}

// ReadOnlyViewModel não depende de métodos de escrita
class ReadOnlyViewModel(
    private val reader: UserReader
)

Um exemplo iOS com separação de protocolos para trabalhar com média:

swift
// Violação de ISP: um protocolo para todo o trabalho com média
protocol MediaService {
    func play(url: URL)
    func pause()
    func stop()
    func upload(data: Data) async -> URL
    func download(url: URL) async -> Data
}

// Após ISP: separação em protocolos por responsabilidade
protocol MediaPlayer {
    func play(url: URL)
    func pause()
    func stop()
}

protocol MediaTransfer {
    func upload(data: Data) async -> URL
    func download(url: URL) async -> Data
}

// PlayerViewModel não depende de métodos de download
class PlayerViewModel {
    private let player: MediaPlayer
}

Conclusão prática: ISP protege os clientes de alterações em partes não relacionadas da interface. Dividir UserRepository em UserReader e UserWriter significa que alterações em save não afetam ReadOnlyViewModel, e vice-versa. Cada cliente está isolado da funcionalidade que não usa e não requer alterações quando outras partes do sistema são modificadas.

ISP e SRP — um par natural. SRP define que uma classe deve ter uma única razão para mudar. ISP aplica a mesma lógica às interfaces: uma interface deve servir um cenário de cliente. Uma classe pode implementar várias interfaces estreitas (cada uma correspondendo a uma responsabilidade), o que é mais limpo do que uma interface gorda com múltiplas responsabilidades.

ISP e OCP também estão relacionados: interfaces estreitas são mais fáceis de estender. Adicionar um novo método a uma interface estreita afeta apenas os seus clientes. Adicionar um método a uma interface gorda afeta todos os clientes — potencialmente violando OCP se os clientes forem forçados a alterar a sua implementação.

ISP e DIP trabalham juntos: DIP exige dependência de abstrações. ISP torna essas abstrações estreitas e focadas. Depender de uma interface ampla ainda é uma dependência de uma abstração, mas uma abstração “má” da perspetiva de ISP. Quatro princípios (SRP, OCP, ISP, DIP) formam a “pirâmide de modularidade”: SRP e ISP definem limites, OCP e DIP definem formas de extensão e acoplamento.

Aplicação de ISP na arquitetura de componentes

A arquitetura de componentes em projetos móveis (módulos, funcionalidades, camadas) beneficia-se de ISP ao nível de APIs públicas. Cada módulo exporta interfaces estreitas para os seus consumidores, em vez de uma única fachada comum. Isto permite alterar a implementação interna do módulo sem afetar os consumidores que usam apenas parte da sua funcionalidade.

Em projetos Android com Clean Architecture, ISP é aplicado a UseCases: cada UseCase é uma interface separada com um único método invoke ou execute. O cliente (ViewModel) depende apenas do UseCase de que precisa, em vez de um repositório completo. Isto torna as dependências transparentes e testáveis.

Perguntas frequentes

ISP leva a um número excessivo de interfaces?

Sim, a divisão excessiva é possível. ISP não exige uma interface por cada método. O critério é: existe um cliente que precisa apenas de parte dos métodos da interface? Se todos os clientes usam todos os métodos — a interface não precisa ser dividida. O nível ótimo de divisão é determinado por cenários de uso reais.

Como ISP é aplicado aos parâmetros de funções?

ISP ao nível de parâmetros significa: uma função não deve aceitar objetos com muitos campos se usa apenas parte deles. Em vez disso, devem ser passados apenas os dados necessários ou usar interfaces especializadas (por exemplo, uma interface Renderable em vez de um User completo).

Como ISP difere de LSP?

LSP trata da herança correta e compatibilidade comportamental de subtipos. ISP trata do design de interfaces: os clientes não devem depender de métodos que não usam. LSP responde à pergunta “pode uma subclasse ser usada em vez da classe base?”, ISP responde “o cliente precisa da interface completa?”

Como ISP simplifica os testes?

Interfaces estreitas simplificam a criação de objetos mock: o teste cria um mock com um ou dois métodos, não com uma dúzia. Quanto menos métodos uma interface tiver, mais fácil é simular o seu comportamento. Isso reduz a carga cognitiva do programador de testes e diminui a probabilidade de erros na lógica mock.

Quando se pode prescindir de ISP?

Se a interface for estável e todos os clientes usarem todos os métodos — a divisão é redundante. Um exemplo típico: os protocolos UIKit desenhados pela Apple. Dividi-los é arriscado porque o UIKit espera a implementação completa do delegado. Nesses casos, a violação de ISP é justificada pela estabilidade da API.

Resumo

  • ISP (Interface Segregation Principle) — o princípio de segregação de interfaces, o quarto em SOLID
  • O cliente não deve depender de métodos que não usa
  • Interfaces gordas forçam as classes a implementar métodos desnecessários como stubs ou exceções
  • A divisão de interfaces reduz o acoplamento e isola os clientes de alterações
  • ISP + SRP formam os limites dos módulos: uma responsabilidade — um contrato estreito
  • Testes mock são simplificados: uma interface estreita requer menos stubs
  • A divisão ótima é determinada por cenários reais de cliente, não pela divisão máxima

Vamos desenvolver um aplicativo móvel chave na mão

A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.

Discutir o projeto

Leia também