Princípios SOLID em JavaScript: implementação avançada e exemplos de código

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

Introdução: SOLID no ecossistema JavaScript

SOLID é um acrônimo de cinco princípios fundamentais de design orientado a objetos, formulados por Robert Martin. No contexto do JavaScript, especialmente ao desenvolver em Node.js com TypeScript e frameworks modernos (NestJS, Express), esses princípios se tornam criticamente importantes para construir aplicações escaláveis e sustentáveis. Em nível avançado, o SOLID vai além de classes e interfaces simples, abordando a arquitetura de módulos, injeção de dependências e testes.

Neste artigo, examinaremos cada princípio SOLID com exemplos de código para Node.js, focando em nuances práticas e erros típicos. Você aprenderá como aplicar SOLID em projetos reais, usando os recursos do JavaScript (ES6+) e TypeScript.



1. Princípio da Responsabilidade Única (SRP) em JavaScript

Teoria: Uma classe ou módulo deve ter apenas um motivo para mudar. Em JavaScript, isso é frequentemente violado quando lógica de negócios, trabalho com banco de dados e formatação de respostas são misturados em um único arquivo.

Prática (Node.js): Separe as responsabilidades no nível de serviços e repositórios.

// ❌ Violação do SRP: a classe processa requisições, valida e salvaclass UserService {    createUser(data) {        if (!data.email) throw new Error('Email required');        const db = new Database();        return db.save('users', data);    }}

// ✅ Cumprimento do SRP: separação em validador, repositório e serviçoclass UserValidator { validate(data) { if (!data.email) throw new Error('Email required'); }}

class UserRepository { constructor(db) { this.db = db; } save(data) { return this.db.save('users', data); }}

class UserService { constructor(validator, repository) { this.validator = validator; this.repository = repository; } createUser(data) { this.validator.validate(data); return this.repository.save(data); }}

Use injeção de dependências (DI) para passar o validador e o repositório para o serviço. Isso simplifica os testes e a substituição de componentes.



2. Princípio do Aberto/Fechado (OCP) através de polimorfismo

Teoria: As classes devem estar abertas para extensão, mas fechadas para modificação. Em JavaScript, isso é alcançado por meio de herança, composição ou estratégias.

Prática (Node.js com TypeScript): Use classes abstratas ou interfaces para definir um contrato.

// Classe abstrata para relatóriosabstract class ReportGenerator {    abstract generate(data: any): string;}

class PDFReport extends ReportGenerator { generate(data: any): string { return `PDF: ${JSON.stringify(data)}`; }}

class CSVReport extends ReportGenerator { generate(data: any): string { return `CSV: ${data.join(',')}`; }}

// O código cliente não muda ao adicionar novos formatosclass ReportService { constructor(private generator: ReportGenerator) {} createReport(data: any) { return this.generator.generate(data); }}

Para JavaScript puro, use fábricas ou estratégias (padrão Strategy) para evitar modificar o código existente.



3. Princípio da Substituição de Liskov (LSP) em código assíncrono

Teoria: Objetos de uma classe base devem ser substituíveis por objetos de uma classe derivada sem quebrar o programa. Em JavaScript, o LSP é frequentemente violado ao sobrescrever métodos com contratos diferentes (por exemplo, tipos de retorno ou exceções).

Prática (Node.js com async/await): Certifique-se de que as subclasses não enfraqueçam as pré-condições nem fortaleçam as pós-condições.

class Database {    async connect() { return 'con                

Blogs

Book Recommendations