Desenvolvimento Web

SOLID na Pratica: Os 5 Principios Que Transformam Codigo Baguncado em Codigo Profissional

SOLID na Pratica: Os 5 Principios Que Transformam Codigo Baguncado em Codigo Profissional

SOLID e um acronimo de cinco principios de design orientado a objetos que tornam o software mais compreensivel, flexivel e manutenivel. Formulados por Robert C. Martin (Uncle Bob), sao fundamentais para qualquer desenvolvedor que queira escrever codigo profissional. Este guia explica cada principio com exemplos praticos.

S – Single Responsibility Principle (SRP)

Principio: uma classe deve ter apenas um motivo para mudar. Ou seja, cada classe deve ter uma unica responsabilidade.

Ruim:
class UserService:
def create_user(self, name, email, password):
# Validacao
if not re.match(r”[^@]+@[^@]+.[^@]+”, email):
raise ValueError(“Email invalido”)

# Criptografia
hashed = bcrypt.hashpw(password.encode(), bcrypt.gensalt())

# Banco de dados
db.execute(“INSERT INTO users (name, email, password) VALUES (?, ?, ?)”, (name, email, hashed))

# Envio de email
smtp.sendmail(“noreply@app.com”, email, “Bem-vindo!”)

Esta classe tem 4 responsabilidades: validacao, criptografia, persistencia e envio de email. Qualquer mudanca em uma dessas areas exige alterar esta classe.

Bom:
class UserValidator:
def validate(self, name, email, password):
if not re.match(r”[^@]+@[^@]+.[^@]+”, email):
raise ValueError(“Email invalido”)

class UserRepository:
def save(self, user):
db.execute(“INSERT INTO users VALUES (?)”, user)

class WelcomeEmailService:
def send(self, email):
smtp.sendmail(“noreply@app.com”, email, “Bem-vindo!”)

class UserService:
def __init__(self, validator, repository, email_service):
self.validator = validator
self.repository = repository
self.email_service = email_service

def create_user(self, name, email, password):
self.validator.validate(name, email, password)
user = User(name, email, hash_password(password))
self.repository.save(user)
self.email_service.send(email)

Cada classe tem uma responsabilidade. Mudar como emails sao enviados nao afeta a persistencia.

O – Open/Closed Principle (OCP)

Principio: classes devem ser abertas para extensao, fechadas para modificacao. Voce deve poder adicionar comportamento sem alterar codigo existente.

Ruim:
class DescontoCalculator:
def calcular(self, tipo, valor):
if tipo == “black_friday”:
return valor * 0.7
elif tipo == “natal”:
return valor * 0.85
elif tipo == “aniversario”:
return valor * 0.9
return valor

Cada novo tipo de desconto exige modificar esta classe.

Bom:
class Desconto(ABC):
@abstractmethod
def aplicar(self, valor):
pass

class BlackFridayDesconto(Desconto):
def aplicar(self, valor):
return valor * 0.7

class NatalDesconto(Desconto):
def aplicar(self, valor):
return valor * 0.85

# Para adicionar novo desconto: crie uma nova classe. Zero modificacao no codigo existente.

L – Liskov Substitution Principle (LSP)

Principio: subclasses devem poder substituir suas superclasses sem quebrar o programa. Se B herda de A, voce deve poder usar B em qualquer lugar que espera A.

Violacao classica: Retangulo e Quadrado. Quadrado herda de Retangulo, mas ao setar largura de um Quadrado tambem muda a altura — comportamento inesperado para quem espera um Retangulo.

A solucao: prefira composicao sobre heranca. Se Quadrado nao se comporta como Retangulo em todos os cenarios, nao deveria herdar de Retangulo.

I – Interface Segregation Principle (ISP)

Principio: clientes nao devem depender de interfaces que nao usam. Prefira muitas interfaces especificas a uma interface generica grande.

Ruim: interface Worker com metodos work(), eat(), sleep(). Um robo implementa Worker mas nao come nem dorme — forcado a ter metodos vazios.

Bom: interfaces separadas Workable(work), Eatable(eat), Sleepable(sleep). O robo implementa apenas Workable.

D – Dependency Inversion Principle (DIP)

Principio: modulos de alto nivel nao devem depender de modulos de baixo nivel. Ambos devem depender de abstracoes.

Ruim:
class OrderService:
def __init__(self):
self.db = PostgreSQLDatabase() # Dependencia direta!
self.email = GmailService() # Dependencia direta!

Bom:
class OrderService:
def __init__(self, db: Database, email: EmailService):
self.db = db
self.email = email

# Injecao de dependencia:
order_service = OrderService(db=PostgreSQLDatabase(), email=GmailService())
# Em testes:
order_service = OrderService(db=InMemoryDatabase(), email=FakeEmailService())

O OrderService depende de abstracoes (Database, EmailService), nao de implementacoes concretas. Isso permite trocar implementacoes facilmente — inclusive para testes.

SOLID na pratica do dia a dia

Nao aplique SOLID cegamente. Em projetos pequenos ou scripts, SOLID pode ser over-engineering. A chave e reconhecer QUANDO o principio resolve um problema real: se voce precisa adicionar comportamento frequentemente (use OCP). Se classes estao crescendo demais (aplique SRP). Se testes exigem setup complexo (aplique DIP). SOLID e um guia, nao dogma.

Tem um projeto em mente?

Somos especialistas em transformar ideias em produtos digitais. Apps, sites, automações e IA — vamos construir juntos.

Resposta rápida Orçamento sem compromisso +100 projetos entregues
Compartilhar: