Entendendo SOLID no Angular: Como escrever código limpo e sustentável
Se você já passou por aquele caos de manter um projeto Angular que começou pequeno e virou um monstro, provavelmente percebeu a importância de ter um código limpo e fácil de manter. É aí que entra o SOLID — um conjunto de princípios que ajudam a escrever software melhor.
Neste post, vou te explicar cada letra de forma simples e mostrar como você pode aplicar esses conceitos no dia a dia com Angular.
S – Single Responsibility Principle (Princípio da Responsabilidade Única)
O que é?
Uma classe (ou componente, serviço, etc.) deve ter uma única responsabilidade — ou seja, ela deve fazer só uma coisa, e fazer bem feito.
No Angular:
Evite aquele Component
que além de exibir a tela, também valida formulário, faz chamadas HTTP, formata data e ainda gera PDF. Que tal separar?
Exemplo prático:
UserComponent
→ mostra os dados.UserService
→ busca os dados do backend.DateFormatterService
→ formata datas.
Separar responsabilidades deixa o código mais testável e fácil de manter.
O – Open/Closed Principle (Aberto para Extensão, Fechado para Modificação)
O que é?
Você deve poder adicionar novas funcionalidades sem precisar mudar o que já existe.
No Angular:
Use herança, injeção de dependência e interfaces para extender comportamentos.
Exemplo prático:
Imagine um serviço de envio de notificações:
CopiarEditarexport interface Notifier {
notify(message: string): void;
}
Crie implementações separadas:
CopiarEditarexport class EmailNotifier implements Notifier {
notify(message: string) { /* envia email */ }
}
export class ToastNotifier implements Notifier {
notify(message: string) { /* mostra toast */ }
}
Agora você pode adicionar novos tipos de notificação sem mudar o código original.
L – Liskov Substitution Principle (Princípio da Substituição de Liskov)
O que é?
Se você usar uma subclasse no lugar da classe base, tudo deve continuar funcionando corretamente.
No Angular:
Se você criar um componente base ou serviço genérico, suas versões estendidas devem manter o comportamento esperado.
Exemplo prático:
Tem um BaseFormComponent
com lógica de validação comum? Se você fizer um UserFormComponent extends BaseFormComponent
, o comportamento base deve continuar válido.
Evite sobrescrever métodos sem manter o contrato original.
I – Interface Segregation Principle (Princípio da Segregação de Interfaces)
O que é?
É melhor ter várias interfaces pequenas do que uma única interface cheia de métodos que nem sempre são usados.
No Angular:
Em vez de criar uma interface gigante como CrudService
com create
, read
, update
, delete
, restore
, archive
, etc… crie interfaces específicas.
Exemplo prático:
tsCopiarEditarexport interface Creatable<T> {
create(item: T): Observable<T>;
}
export interface Readable<T> {
getById(id: number): Observable<T>;
}
Agora, serviços usam só o que precisam, mantendo o código mais limpo.
D – Dependency Inversion Principle (Princípio da Inversão de Dependência)
O que é?
Dependa de abstrações, não de implementações concretas.
No Angular:
Use interfaces + injeção de dependência para desacoplar seu código.
Exemplo prático:
tsCopiarEditarexport abstract class LoggerService {
abstract log(message: string): void;
}
Você pode ter várias implementações:
tsCopiarEditar@Injectable()
export class ConsoleLoggerService extends LoggerService {
log(message: string) {
console.log('[LOG]', message);
}
}
E no AppModule
:
tsCopiarEditarproviders: [
{ provide: LoggerService, useClass: ConsoleLoggerService }
]
Assim, se quiser mudar a implementação, não precisa alterar onde ela é usada.
Conclusão
Aplicar SOLID no Angular não é difícil, e os benefícios são enormes:
- Código mais organizado
- Mais fácil de testar
- Menos dor de cabeça para manter
Comece aos poucos. Reforce a separação de responsabilidades, use interfaces, e sempre pense: “esse código está fácil de entender e manter?”
Se você curtiu esse post, compartilha com aquele colega que vive sofrendo com componentes-gigantes.ts
😅
Publicar comentário