Princípio de segregação de interfaces - Interface Segregation Principle

Os clientes não devem ser forçados a importar métodos que eles não usam. Os métodos devem ser segregados de modo abstrato em interfaces.

Categoria de Programação

Postado em 27 abril 2022

Atualizado em 06 junho 2023

Palavras-chave: isp,interface,segregation,principle,princípio,segregação,solid

Visualizações: 2448

É bastante comum declarar vários métodos em uma mesma classe quando esses métodos possuem algum tema em comum. Essa prática tem seus altos e baixos. Separar as classes por tema pode facilitar a localização das funções. Porém, juntar vários métodos em uma única classe viola o princípio de responsabilidade única. Segundo Robert Martin, autor da arquitetura limpa, o princípio da responsabilidade única foi de autoria de Tom DeMarco, que dizia que uma classe deve fazer apenas uma coisa e bem feita. Isso não significa que uma classe só deve ter uma função. O verdadeiro problema é quando uma classe realiza várias atividades como criação de lista de dados, registro de novos dados, atualização de dados existentes e assim por diante.

Um dos principais objetivos do princípio da responsabilidade única é diminuir o acoplamento entre classes. Diminuir o acoplamento entre classes, significa ter mais flexibilidade na manutenção de um software. Mais flexibilidade traz maior produtividade e menos custos de manutenção. Enfim, o acoplamento estratégico entre classes pode livrar os desenvolvedores de desastres ao longo prazo.

Uma boa estratégia é evitar que as classes fiquem “gordas”. Robert Martin diz que classes que fazem mais do que o necessário são classes gordas. O princípio de segregação de interfaces evita que as classes fiquem gordas.

O que é o princípio de segregação de interfaces (ISP)?

O princípio de segregação de interfaces (Single Responsibility Principle) é o quarto princípio SOLID. Esse princípio diz que um cliente não deve depender de métodos que ele não usa. O cliente se refere a uma classe ou a um módulo. Quando importamos uma classe para usar um método, estamos importando todos os outros métodos dessa classe.

exemplo de classe gorda princípio de segregação de interfaces

No exemplo acima, a classe ZZ importa as classes A e B para usar os métodos A e B. Ao importar a classe B, a classe ZZ também importa os métodos C, D e E automaticamente. Querendo ou não, agora a classe ZZ também depende dos métodos que ela não usa. Isso quer dizer que se um erro ou excessão acontecer nos métodos C, D ou E, a classe ZZ terá o seu funcionamento afetado. Além da redundância, agora a classe ZZ tem que estar preocupada com o funcionamento de métodos que ela não usa.

O princípio de segregação de interfaces é uma solução para evitar a importação de métodos desnecessários usando abstração. Invés de usar os métodos diretamente de uma classe concreta (classe não abstrata), a classe utilizadora usa métodos pré-definidos em interfaces.

exemplo de como aplicar o princípio de segregação de interfaces isp

Agora a classe ZZ irá importar apenas os métodos que ela usa. Outra grande vantagem é que agora os detalhes dependem de abstrações. Assim, estamos obedecendo ao ISP e a regra das dependências.

Como aplicar o princípio de segregação de interfaces (ISP)?

O uso de interfaces na classe utilizadora podem ser realizados sem a presença dos detalhes. Os detalhes podem ser implementados posteriormente, após a definição das abstrações e da classe utilizadora.

interface InterfaceA {
    void methodA();
}

interface InterfaceB {
    void methodB();
}

A interfaceA e a interfaceB são abstrações. As abstrações podem ser usados como o tipo de parâmetro na classe utilizadora.

class ClasseZZ {
    InterfaceA interfaceA;
    InterfaceB interfaceB;
	
	public ZZ(InterfaceA interfaceA, InterfaceB interfaceB) {
		this.interfaceA = interfaceA;
		this.interfaceB = interfaceB;
	}
	
	public void doA() {
		this.interfaceA.methodA();
	}
	
	public void doB() {
		this.interfaceB.methodB();
	}
}

Se olharmos as dependências no diagrama da imagem acima, a classe ZZ usa as abstrações e os detalhes implementam as abstrações. Uma abstração precisa ser implementada para poder ser instanciada. Esse é o papel dos detalhes.

class ClasseA implements InterfaceA {
	public void methodA() {
		// Escreve os detalhes
	}
}

Uma vez que as abstrações, os detalhes e a classe utilizadora foram definidos, podemos instanciar essas classes para execução.

ClasseA classeA = new ClasseA();
ClasseB classeB = new ClasseB();
ClasseZZ classeZZ = new ClasseZZ(classeA, classeB);
classeZZ.doA();

A classe B também implementa métodos que a classe ZZ não usa. Porém, pelo fato da classe ZZ ter definido uma interface contendo apenas os métodos necessários no construtor, ela não importa os outros métodos implementados na classe B. Assim, estamos de acordo com o princípio de segregação de interfaces.

Como dividir as interfaces usando o princípio de segregação de interfaces (ISP)?

A divisão de interfaces no ISP depende do contexto do software. O ideal é que cada interface não fique nem muito volumosa e nem muito escassa. Interfaces volumosas (contendo vários métodos) obrigam o cliente (classe utilizadora) a implementar métodos que ela não precisa. Interfaces escassas geram excesso de granularidade. Há quem diga que podemos dividir as interfaces por utilizador, porém esse tipo de segregação não é muito interessante.

Robert Martin recomenda segregar as interfaces por grupos de clientes. Os clientes que usam as mesmas interfaces pertencem ao mesmo grupo. Assim, as interfaces são criadas para cada grupo em vez de cada cliente.

exemplo de como dividir as interfaces no princípio de segregação de interfaces isp

No exemplo acima, os clientes são divididos em grupos (cada grupo é uma cor). Se necessário, um cliente também pode usar múltiplas interfaces.

Como substituir as interfaces existentes na manutenção?

O ideal seria substituir a interface atual pela nova. Porém, há casos que o impacto dessa mudança é muito grande. Um bom truque é fazer uma conversão dinâmica (cast) dentro do cliente que usa a interface e manter a interface existente. Assim, as novas interfaces podem ser usadas imediatamente.

Conclusão

O princípio de segregação de interfaces diz que uma classe não deve ser muito gorda, pois isso forçaria clientes (classes utilizadoras) a importar métodos desnecessários. As interfaces devem ser específicas para que os clientes importem apenas métodos que eles utilizam.

Projetos práticos

Tutorial de programação do jogo da serpente em javascript

Programando o clássico jogo da serpente usando o framework p5.js. Tutorial indicado para iniciantes da programação que querem aprender os conceitos básico da área criando jogos.

Criando o esqueleto de um jogo de tiro 2D visto de cima usando P5.js

Usando lógicas matemáticas como trigonometria para criar e calcular o esqueleto de um jogo de tiro 2D em javascript

Criando um jogo de guerra nas estrelas em javascript usando a biblioteca p5.js

Jogo simples de guerra espacial desenvolvido em javascript. Esse jogo usa cálculos de física para simular efeitos de atrito e inércia.

Caixa eletrônico usando arquitetura limpa

Usando JavaFX e arquitetura limpa para criar um aplicativo de caixa eletrônico extremamente simples.

Integrando Laravel com o protocolo MQTT para comunicação entre dispositivos

Projeto de comunicação entre dois dispositivos ESP8266 e Raspberrypi4. Laravel irá funcionar como servidor e receptor de dados de temperatura e umidade coletados com o DHT11.

Veja também

Estar antenado pode te salvar de cair em algum golpe

A engenharia social é a forma mais fácil de roubar os dados da vítima, principalmente aqueles que não estão antenados..

Nunca se sabe quando tem alguém nos espionando no nosso computador

Um computador conectado à internet está exposto a diversos perigos. O spyware é um deles e é esse malware responsável por roubar contas de redes sociais.

Memória de computador

O computador possui memória primária e memória auxiliar, ambos possuem finalidades específicas como armazenamento de dados temporários ou permanentes.

Princípio aberto fechado - Open-Closed Principle

O código deve estar aberto para extensões e fechado para modificações. Podemos mudar o comportamento de uma classe adicionando mais código.

Link dedicado

Link dedicado é um caminho físico exclusivo que liga a empresa com o provedor diretamente, possibilitando a transferência de dados e o acesso à internet.

Princípio da responsabilidade única - Single Responsibility Principle

Princípio que diz que um módulo só deve mudar por um único motivo. Esse motivo pode ser o conteúdo de um módulo ou os atores que dependem dele.