Princípios SOLID em TypeScript: teoria e prática do A ao Z

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Princípios SOLID em TypeScript: teoria e prática do A ao Z

\n\n

SOLID é um acrônimo de cinco princípios fundamentais da programação orientada a objetos, formulados por Robert Martin (Tio Bob). Esses princípios ajudam a criar código flexível, sustentável e escalável. Neste artigo, vamos detalhar cada princípio SOLID com exemplos em TypeScript, desde definições simples até cenários reais de uso.

\n\n

1. Single Responsibility Principle (SRP) — Princípio da Responsabilidade Única

\n\n

Definição: Cada classe deve ter apenas um motivo para mudar. Em outras palavras, a classe deve ser responsável por uma tarefa claramente definida.

\n\n

Problema: Quando uma classe assume várias responsabilidades, torna-se difícil testá-la, estendê-la e mantê-la. A alteração de uma função pode quebrar outra.

\n\n

Exemplo de violação do SRP:

\n
// ❌ Violação do SRP: a classe lida com armazenamento, formatação e envio\nclass UserService {\n    saveUser(user: User): void {\n        // Salvando no banco de dados\n        console.log('User saved');\n    }\n\n    formatUserData(user: User): string {\n        return `Name: ${user.name}, Email: ${user.email}`;\n    }\n\n    sendWelcomeEmail(user: User): void {\n        // Enviando email\n        console.log('Email sent');\n    }\n}
\n\n

Solução com SRP:

\n
// ✅ Cada classe é responsável por sua tarefa\nclass UserRepository {\n    save(user: User): void {\n        console.log('User saved');\n    }\n}\n\nclass UserFormatter {\n    format(user: User): string {\n        return `Name: ${user.name}, Email: ${user.email}`;\n    }\n}\n\nclass EmailService {\n    sendWelcome(user: User): void {\n        console.log('Email sent');\n    }\n}
\n\n

2. Open-Closed Principle (OCP) — Princípio Aberto/Fechado

\n\n

Definição: As classes devem estar abertas para extensão, mas fechadas para modificação. Isso significa que você deve ser capaz de adicionar novas funcionalidades sem alterar o código existente.

\n\n

Exemplo de violação do OCP:

\n
// ❌ Ao adicionar um novo tipo de forma, será necessário alterar o método calculateArea\nclass AreaCalculator {\n    calculateArea(shape: any): number {\n        if (shape.type === 'circle') {\n            return Math.PI * shape.radius ** 2;\n        } else if (shape.type === 'rectangle') {\n            return shape.width * shape.height;\n        }\n        throw new Error('Unknown shape');\n    }\n}
\n\n

Solução com OCP (usando polimorfismo):

\n
// ✅ Usando interface e herança\ninterface Shape {\n    area(): number;\n}\n\nclass Circle implements Shape {\n    constructor(private radius: number) {}\n    area(): number {\n        return Math.PI * this.radius ** 2;\n    }\n}\n\nclass Rectangle implements Shape {\n    constructor(private width: number, private height: number) {}\n    area(): number {\n        return this.width * this.height;\n    }\n}\n\nclass AreaCalculator {\n    calculateArea(shape: Shape): number {\n        return shape.area(); // Não requer alterações ao adicionar novas formas\n    }\n}
\n\n

3. Liskov Substitution Principle (LSP) — Princípio da Substituição de Liskov

\n\n

Definição: Os objetos em um programa devem ser substituíveis por instâncias de seus subtipos sem alterar a correção do programa. A classe filha não deve quebrar o contrato da classe pai.

\n\n

Exemplo de violação do LSP:

\n
// ❌ Violação: a subclasse altera o comportamento da superclasse\nclass Bird {\n    fly(): void {\n        console.log('Flying');\n    }\n}\n\nclass Penguin extends Bird {\n    fly(): void {\n        throw new Error('Penguins cannot fly!'); // Quebra do contrato\n    }\n}
\n\n

Solução com LSP:

\n
// ✅ Separação                

Blogs

Book Recommendations