Princípios SOLID em JavaScript: 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 JavaScript: teoria e prática do A ao Z

\n\n

O desenvolvimento de software de qualidade exige não apenas o conhecimento da sintaxe da linguagem, mas também a compreensão dos princípios de arquitetura. SOLID são cinco princípios fundamentais de design orientado a objetos que ajudam a criar código flexível, sustentável e escalável. Neste artigo, analisaremos cada princípio SOLID no contexto do JavaScript (Node.js) com exemplos práticos.

\n\n

O que é SOLID?

\n\n

O acrônimo SOLID foi introduzido por Robert Martin (Uncle Bob) e inclui os seguintes princípios:

\n\n
    \n
  • S — Single Responsibility Principle (Princípio da Responsabilidade Única)
  • \n
  • O — Open/Closed Principle (Princípio Aberto/Fechado)
  • \n
  • L — Liskov Substitution Principle (Princípio da Substituição de Liskov)
  • \n
  • I — Interface Segregation Principle (Princípio da Segregação de Interface)
  • \n
  • D — Dependency Inversion Principle (Princípio da Inversão de Dependência)
  • \n
\n\n

Esses princípios são universais e aplicáveis a qualquer linguagem de programação, incluindo JavaScript. Vamos examinar cada um deles em detalhes.

\n\n

1. Single Responsibility Principle (SRP)

\n\n

Definição: Uma classe ou módulo deve ter apenas um motivo para mudar. Em outras palavras, cada módulo é responsável por uma tarefa específica.

\n\n

Exemplo ruim: A classe UserService, que é responsável por salvar o usuário, enviar e-mail e gerar relatórios.

\n\n
// ❌ Violação do SRP\nclass UserService {\n    saveUser(user) {\n        // Salvar no banco de dados\n        console.log('User saved');\n    }\n\n    sendEmail(user) {\n        // Enviar e-mail\n        console.log('Email sent to ' + user.email);\n    }\n\n    generateReport(user) {\n        // Gerar relatório\n        console.log('Report generated for ' + user.name);\n    }\n}
\n\n

Exemplo bom: Dividimos a responsabilidade em classes separadas.

\n\n
// ✅ Cumprimento do SRP\nclass UserRepository {\n    save(user) {\n        console.log('User saved');\n    }\n}\n\nclass EmailService {\n    send(user) {\n        console.log('Email sent to ' + user.email);\n    }\n}\n\nclass ReportGenerator {\n    generate(user) {\n        console.log('Report generated for ' + user.name);\n    }\n}\n\n// Uso\nconst user = { name: 'Иван', email: 'ivan@example.com' };\nconst userRepo = new UserRepository();\nconst emailService = new EmailService();\nconst reportGen = new ReportGenerator();\n\nuserRepo.save(user);\nemailService.send(user);\nreportGen.generate(user);
\n\n

Agora cada classe tem uma única responsabilidade, e as alterações em um módulo não afetam os outros.

\n\n

2. Open/Closed Principle (OCP)

\n\n

Definição: Entidades de software (classes, módulos, funções) devem estar abertas para extensão, mas fechadas para modificação.

\n\n

Exemplo ruim: Uma função que calcula a área de formas usando operadores condicionais.

\n\n
// ❌ Violação do OCP\nfunction calculateArea(shape) {\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    // Ao adicionar uma nova forma, é necessário modificar a função\n    return 0;\n}
\n\n

Exemplo bom: Usamos polimorfismo e herança.

\n\n
// ✅ Cumprimento do OCP\nclass Shape {\n    area() {\n        throw new Error('O método area() deve ser implementado');\n    }\n}\n\nclass Circle extends Shape {\n    constructor(radius) {\n        super();\n        this.radius = radius;\n    }\n\n    area() {\n        return Math.PI * this.radius ** 2;\n    }\n}\n\nclass Rectangle extends Shape {\n    constructor                

Blogs

Book Recommendations