Conceitos
SOLID é um acrônimo que representa cinco princípios fundamentais da programação orientada a objetos, propostos por Robert C. Martin - o uncle Bob. Aqui você pode ler mais sobre o artigo dele.
Esses princípios têm como objetivo melhorar a estrutura e a manutenção do código, tornando-o mais flexível, escalável e fácil de entender. Tais princípios auxiliam o programador a criar códigos mais organizados, dividindo responsabilidades, reduzindo dependências, simplificando o processo de refatoração e promovendo a reutilização do código.
O "I" do acrônimo significa "Interface Segregation Principle". A frase que o uncle bob utilizou para definir esse princípio foi:
"Nenhum cliente deve ser forçado a depender de interfaces que não utiliza"
O Princípio da Segregação da Interface aborda um problema comum: interfaces excessivamente grandes que forçam implementações desnecessárias em classes que não precisam delas.
Aplicação prática
Imagine um sistema de autenticação em uma aplicação, onde diferentes métodos são usados para autenticar um usuário (e.g., por senha, por biometria, por QR Code).
Primeiro, vejamos a aplicação dessa classe sem utilizar o ISP em Java e Typescript:
Java
interface Authenticator {
boolean authenticateWithPassword(String userId, String password);
boolean authenticateWithBiometrics(String userId);
boolean authenticateWithQRCode(String qrCode);
}
class PasswordAuthenticator implements Authenticator {
@Override
public boolean authenticateWithPassword(String userId, String password) {
System.out.println("Authenticating with password...");
return true;
}
@Override
public boolean authenticateWithBiometrics(String userId) {
throw new UnsupportedOperationException("Not implemented");
}
@Override
public boolean authenticateWithQRCode(String qrCode) {
throw new UnsupportedOperationException("Not implemented");
}
}
Typescript
interface Authenticator {
authenticateWithPassword(userId: string, password: string): boolean;
authenticateWithBiometrics(userId: string): boolean;
authenticateWithQRCode(qrCode: string): boolean;
}
class PasswordAuthenticator implements Authenticator {
authenticateWithPassword(userId: string, password: string): boolean {
console.log("Authenticating with password...");
return true;
}
authenticateWithBiometrics(userId: string): boolean {
throw new Error("Not implemented");
}
authenticateWithQRCode(qrCode: string): boolean {
throw new Error("Not implemented");
}
}
Problemas:
-
Métodos não utilizados: A classe
PasswordAuthenticator
implementa métodos que não fazem sentido para sua função. - Manutenção problemática: Se a interface mudar, todas as classes implementadoras precisam ser alteradas, mesmo que não utilizem os métodos novos.
- Violação de responsabilidade única: As classes começam a lidar com preocupações que não deveriam ser delas.
Para resolver o problema, podemos dividir a interface Authenticator
em interfaces menores e mais específicas.
Java
interface PasswordAuth {
boolean authenticateWithPassword(String userId, String password);
}
interface BiometricAuth {
boolean authenticateWithBiometrics(String userId);
}
interface QRCodeAuth {
boolean authenticateWithQRCode(String qrCode);
}
class PasswordAuthenticator implements PasswordAuth {
@Override
public boolean authenticateWithPassword(String userId, String password) {
System.out.println("Authenticating with password...");
return true;
}
}
class BiometricAuthenticator implements BiometricAuth {
@Override
public boolean authenticateWithBiometrics(String userId) {
System.out.println("Authenticating with biometrics...");
return true;
}
}
class QRCodeAuthenticator implements QRCodeAuth {
@Override
public boolean authenticateWithQRCode(String qrCode) {
System.out.println("Authenticating with QR Code...");
return true;
}
}
Typescript
interface PasswordAuth {
authenticateWithPassword(userId: string, password: string): boolean;
}
interface BiometricAuth {
authenticateWithBiometrics(userId: string): boolean;
}
interface QRCodeAuth {
authenticateWithQRCode(qrCode: string): boolean;
}
class PasswordAuthenticator implements PasswordAuth {
authenticateWithPassword(userId: string, password: string): boolean {
console.log("Authenticating with password...");
return true;
}
}
class BiometricAuthenticator implements BiometricAuth {
authenticateWithBiometrics(userId: string): boolean {
console.log("Authenticating with biometrics...");
return true;
}
}
class QRCodeAuthenticator implements QRCodeAuth {
authenticateWithQRCode(qrCode: string): boolean {
console.log("Authenticating with QR Code...");
return true;
}
}
Benefícios da Refatoração
- Interfaces específicas: Cada classe implementa apenas os métodos que realmente utiliza.
- Flexibilidade: Adicionar novos métodos ou modos de autenticação não impacta implementações existentes.
- Manutenção mais simples: Reduz o impacto de mudanças no código, evitando refatorações desnecessárias.
Top comments (0)