10 de março de 2026 • 4 minutos de leitura
Os princípios SOLID são um conjunto de boas práticas de design de software que ajudam a criar sistemas mais organizados, flexíveis e fáceis de manter. Eles são amplamente utilizados no desenvolvimento orientado a objetos e são considerados uma base importante para escrever código limpo e sustentável.
Conforme aplicações crescem, é comum surgirem problemas como:
Para ajudar a resolver esses problemas, surgiram princípios de design que orientam como estruturar melhor o software. Entre eles, os princípios SOLID são alguns dos mais conhecidos na engenharia de software moderna.
O Single Responsibility Principle afirma que uma classe deve ter apenas uma razão para mudar.
Ou seja, cada classe deve possuir apenas uma responsabilidade dentro do sistema.
Neste exemplo, a mesma classe cria usuários e também envia emails.
class UserService {
createUser(user) {
console.log("Usuário criado")
}
sendEmail(user) {
console.log("Enviando email para usuário")
}
}O problema aqui é que a classe possui duas responsabilidades diferentes.
Se a lógica de envio de email mudar, precisamos alterar essa classe.
class UserService {
createUser(user) {
console.log("Usuário criado")
}
}
class EmailService {
sendEmail(user) {
console.log("Enviando email para usuário")
}
}Agora cada classe possui uma única responsabilidade, facilitando manutenção e testes.
O Open/Closed Principle diz que entidades devem estar abertas para extensão, mas fechadas para modificação.
Isso significa que devemos conseguir adicionar novos comportamentos sem modificar código existente.
class DiscountService {
calculate(type) {
if(type === "regular") {
return 10
}
if(type === "premium") {
return 20
}
}
}Toda vez que surgir um novo tipo de desconto precisamos modificar a classe.
class RegularDiscount {
calculate() {
return 10
}
}
class PremiumDiscount {
calculate() {
return 20
}
}
class DiscountService {
calculate(discountStrategy) {
return discountStrategy.calculate()
}
}Agora podemos criar novos tipos de desconto sem alterar o código existente.
Proposto por Barbara Liskov, esse princípio afirma que uma classe filha deve poder substituir a classe pai sem quebrar o comportamento esperado.
class Bird {
fly() {
console.log("Voando")
}
}
class Penguin extends Bird {
fly() {
throw new Error("Pinguins não voam")
}
}Aqui temos um problema: nem todo pássaro voa.
class Bird {}
class FlyingBird extends Bird {
fly() {
console.log("Voando")
}
}
class Penguin extends Bird {}
class Eagle extends FlyingBird {}Agora apenas pássaros que voam possuem o método fly(), respeitando o princípio.
O Interface Segregation Principle diz que uma classe não deve ser forçada a implementar métodos que não utiliza.
interface Worker {
work()
eat()
sleep()
}
class Robot implements Worker {
work() {
console.log("Trabalhando")
}
eat() {
throw new Error("Robô não come")
}
sleep() {
throw new Error("Robô não dorme")
}
}A interface obriga a classe a implementar métodos que não fazem sentido.
interface Workable {
work()
}
interface Eatable {
eat()
}
class Human implements Workable, Eatable {
work() {
console.log("Trabalhando")
}
eat() {
console.log("Comendo")
}
}
class Robot implements Workable {
work() {
console.log("Trabalhando")
}
}Agora cada classe implementa apenas o que precisa.
O Dependency Inversion Principle afirma que:
class MySQLDatabase {
save(data) {
console.log("Salvando no MySQL")
}
}
class UserService {
constructor() {
this.database = new MySQLDatabase()
}
save(user) {
this.database.save(user)
}
}Aqui o UserService depende diretamente do MySQL.
interface Database {
save(data)
}
class MySQLDatabase implements Database {
save(data) {
console.log("Salvando no MySQL")
}
}
class MongoDatabase implements Database {
save(data) {
console.log("Salvando no MongoDB")
}
}
class UserService {
constructor(database) {
this.database = database
}
save(user) {
this.database.save(user)
}
}Agora podemos trocar o banco facilmente:
new UserService(new MySQLDatabase())
ou
new UserService(new MongoDatabase())
Os princípios SOLID ajudam a estruturar melhor o código e a criar sistemas mais fáceis de manter, testar e evoluir.
Ao aplicar esses princípios, conseguimos:
Embora nem sempre seja necessário aplicar todos os princípios em todas as situações, compreender SOLID é um passo importante para escrever software de qualidade.