Princípios SOLID em JavaScript: teoria e prática para Node.js

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
```html

Princípios SOLID em JavaScript: da teoria à prática no Node.js

SOLID — são cinco princípios fundamentais de design orientado a objetos, formulados por Robert Martin (Uncle Bob). Esses princípios ajudam a criar código flexível, sustentável e escalável. Embora muitos associem SOLID a linguagens OOP clássicas (Java, C#), eles são perfeitamente aplicáveis também em JavaScript, especialmente no desenvolvimento com Node.js. Neste artigo, vamos analisar cada princípio com exemplos concretos.

Princípio da Responsabilidade Única (Single Responsibility Principle, SRP)

O SRP afirma: "Uma classe (ou módulo) deve ter apenas um motivo para mudar". Isso significa que cada módulo é responsável por uma tarefa específica.

Exemplo ruim (violação do SRP):

class UserService {
    createUser(data) { /* lógica de criação */ }
    sendWelcomeEmail(email) { /* envio de email */ }
    logActivity(action) { /* registro de log */ }
}

Aqui, uma única classe é responsável por trabalhar com usuários, enviar emails e registrar logs. Se o formato do log mudar, será necessário alterar UserService — mesmo que sua tarefa principal não tenha mudado.

Exemplo bom (respeitando o SRP):

class UserRepository {
    createUser(data) { /* apenas interação com o banco de dados */ }
}

class EmailService {
    sendWelcomeEmail(email) { /* apenas envio */ }
}

class Logger {
    logActivity(action) { /* apenas registro de log */ }
}

class UserService {
    constructor(userRepo, emailService, logger) {
        this.userRepo = userRepo;
        this.emailService = emailService;
        this.logger = logger;
    }
    createUser(data) {
        const user = this.userRepo.createUser(data);
        this.emailService.sendWelcomeEmail(user.email);
        this.logger.logActivity('User created');
        return user;
    }
}

Agora cada classe é responsável por sua própria área de responsabilidade. Combinando-as em UserService, obtemos flexibilidade e isolamento de mudanças.

Princípio Aberto/Fechado (Open/Closed Principle, OCP)

O OCP afirma: "Entidades de software devem estar abertas para extensão, mas fechadas para modificação". Ou seja, devemos ser capazes de adicionar novas funcionalidades sem alterar o código existente.

Exemplo ruim (violação do OCP):

class PaymentProcessor {
    processPayment(type, amount) {
        if (type === 'card') { /* processamento de cartão */ }
        else if (type === 'paypal') { /* processamento de PayPal */ }
        // Ao adicionar um novo tipo — é necessário modificar este método
    }
}

Exemplo bom (respeitando o OCP):

class PaymentStrategy {
    pay(amount) { throw new Error('Must be implemented'); }
}

class CardPayment extends PaymentStrategy {
    pay(amount) { console.log(`Paid ${amount} via Card`); }
}

class PayPalPayment extends PaymentStrategy {
    pay(amount) { console.log(`Paid ${amount} via PayPal`); }
}

class PaymentProcessor {
    constructor(strategy) {
        this.strategy = strategy;
    }
    processPayment(amount) {
        this.strategy.pay(amount);
    }
}

// Uso
const cardPayment = new PaymentProcessor(new CardPayment());
cardPayment.processPayment(100);

const paypalPayment = new PaymentProcessor(new PayPalPayment());
paypalPayment.processPayment(200);

Agora, para adicionar um novo método de pagamento, basta criar uma nova classe que herda de PaymentStrategy e passá-la para PaymentProcessor. O código original não é alterado.

Princípio da Substituição de Liskov (Liskov Substitution Principle, LSP)

O LSP afirma: "Os objetos em um programa devem ser substituíveis por instâncias de seus subtipos sem alterar a correção do programa". Em outras palavras, se você tem uma base

```

Blogs

Book Recommendations