Módulo 15 - Empacotamento e boas práticas
Princípios SOLID em Python
11 min de leitura · por Cesar Gargiulo, revisado pela equipe ValorFinal e GuardiaSec · Atualizado em 01/07/2026
O que você vai aprender
- Entender o que cada letra de SOLID representa.
- Aplicar a responsabilidade única para separar motivos de mudança.
- Usar o princípio aberto-fechado para estender sem alterar.
- Reconhecer inversão de dependência com um exemplo em Python.
Ouvir o resumo desta aula
Um recap de cerca de 2 minutos na voz do Valim, para ouvir no trânsito ou na academia.
Ler a transcrição do resumo
Resumo da aula: Princípios SOLID em Python.
Os objetivos desta aula. Entender o que cada letra de SOLID representa. Aplicar a responsabilidade única para separar motivos de mudança. Usar o princípio aberto-fechado para estender sem alterar. Reconhecer inversão de dependência com um exemplo em Python.
Veja o essencial, parte por parte.
O que é SOLID. SOLID são cinco princípios de design orientado a objetos.
Responsabilidade única e aberto-fechado. O primeiro princípio, a responsabilidade única, diz que uma classe deve ter um só motivo para mudar.
Substituição, segregação e inversão. As três letras finais completam o conjunto.
Esse foi o resumo do essencial. Para se aprofundar, leia a aula completa e responda os exercícios.
O que é SOLID
SOLID é um acrônimo para cinco princípios de design que ajudam o código orientado a objetos a envelhecer bem. Eles não são regras rígidas nem uma receita mágica; são diretrizes de bom senso, formuladas para combater os problemas mais comuns de código difícil de mudar. A ideia central por trás de todos é a mesma: reduzir o acoplamento e localizar as mudanças, para que alterar uma parte do sistema não obrigue a mexer em dez outras. Vamos ver cada um com um exemplo simples, sem transformar o assunto em dogma.
| Letra | Princípio | Ideia central |
|---|---|---|
| S | Responsabilidade única | Uma classe, um motivo para mudar |
| O | Aberto-fechado | Estender sem alterar o que existe |
| L | Substituição de Liskov | Subtipo funciona no lugar do tipo base |
| I | Segregação de interfaces | Interfaces pequenas e específicas |
| D | Inversão de dependência | Depender de abstrações, não de detalhes |
As cinco letras de SOLID e a ideia central de cada princípio.
Responsabilidade única e aberto-fechado
O primeiro princípio, a responsabilidade única, diz que uma classe deve ter um só motivo para mudar. Uma classe que calcula um pedido, formata o recibo e ainda envia o e-mail tem três motivos para mudar e mistura três assuntos. Separe: uma classe para o cálculo, outra para a formatação, outra para o envio. Assim, mexer no formato do recibo não arrisca quebrar o cálculo. O segundo, o aberto-fechado, diz que o código deve estar aberto para extensão e fechado para modificação: você adiciona um comportamento novo sem editar o código que já funciona e já foi testado.
from abc import ABC, abstractmethod
# Aberto-fechado: para um novo tipo de desconto, crie uma classe nova,
# sem editar as existentes.
class Desconto(ABC):
@abstractmethod
def aplicar(self, valor: float) -> float: ...
class SemDesconto(Desconto):
def aplicar(self, valor: float) -> float:
return valor
class DescontoPercentual(Desconto):
def __init__(self, percentual: float):
self.percentual = percentual
def aplicar(self, valor: float) -> float:
return valor * (1 - self.percentual / 100)
def preco_final(valor: float, desconto: Desconto) -> float:
return desconto.aplicar(valor)
print(preco_final(100, DescontoPercentual(10))) # 90.0Um novo desconto é uma classe nova, sem tocar em preco_final: aberto para estender, fechado para modificar.
Veja como os dois princípios se reforçam. A função preco_final não conhece os tipos concretos de desconto; ela só sabe que recebe algo com o método aplicar. Para criar uma promoção nova, como um desconto fixo em reais, basta escrever uma classe nova que herda de Desconto. Nada na função preco_final muda, e o código antigo continua intacto e confiável. Sem esse desenho, você acabaria com uma cadeia crescente de if e elif dentro da função, editada e re-testada a cada promoção nova. O bom design troca a edição arriscada pela extensão segura.
Substituição, segregação e inversão
As três letras finais completam o conjunto. A substituição de Liskov diz que um subtipo deve funcionar em qualquer lugar onde o tipo base é esperado, sem surpresas: se uma função aceita uma Ave e você passa um Pinguim, o programa não pode quebrar só porque pinguim não voa. A segregação de interfaces recomenda interfaces pequenas e específicas, em vez de uma interface gigante que obriga classes a implementar métodos que não usam. E a inversão de dependência diz que o código de alto nível deve depender de abstrações, não de detalhes concretos, o que torna as peças intercambiáveis.
from abc import ABC, abstractmethod
# Inversao de dependencia: o RelatorioService depende da abstracao
# Armazenamento, nao de um banco concreto. Trocar de armazenamento
# nao muda o servico.
class Armazenamento(ABC):
@abstractmethod
def salvar(self, texto: str) -> None: ...
class ArmazenamentoArquivo(Armazenamento):
def salvar(self, texto: str) -> None:
print(f"salvando em arquivo: {texto}")
class ArmazenamentoMemoria(Armazenamento):
def __init__(self):
self.dados = []
def salvar(self, texto: str) -> None:
self.dados.append(texto)
class RelatorioService:
def __init__(self, armazenamento: Armazenamento):
self.armazenamento = armazenamento
def gerar(self, conteudo: str) -> None:
self.armazenamento.salvar(f"RELATORIO: {conteudo}")
# Em producao usa arquivo; no teste, memoria. Mesmo servico.
servico = RelatorioService(ArmazenamentoMemoria())
servico.gerar("vendas do mes")Inversão de dependência: o serviço recebe a abstração Armazenamento e não conhece o detalhe concreto.
O exemplo da inversão de dependência mostra o poder prático de SOLID. Como o RelatorioService recebe um Armazenamento qualquer, você usa um armazenamento em arquivo na produção e um em memória nos testes, sem tocar no serviço. Essa é a mesma ideia que torna o código testável e flexível. Um alerta importante: SOLID é um guia, não uma obrigação. Aplicar os cinco princípios a um script de dez linhas é exagero que só adiciona complexidade. Use-os quando a flexibilidade compensa a estrutura extra, que é o caso de sistemas que crescem e mudam com frequência.
Teste rápido
O que diz o princípio da responsabilidade única?
Perguntas frequentes
- Preciso aplicar SOLID em todo código que escrevo?
- Não. SOLID são diretrizes para código que cresce e muda, não regras obrigatórias. Aplicá-las a um script simples só adiciona camadas sem benefício. Use os princípios quando a flexibilidade e a testabilidade que eles trazem realmente compensam a estrutura extra.
- SOLID é só para linguagens muito orientadas a objetos?
- Os princípios nasceram no mundo orientado a objetos, mas as ideias por trás, separar responsabilidades, depender de abstrações e estender sem modificar, valem em qualquer estilo. Em Python, que mistura objetos e funções, você aplica o espírito de SOLID mesmo sem uma hierarquia rígida de classes.
- Qual princípio de SOLID é o mais importante para começar?
- A responsabilidade única costuma dar o maior retorno inicial. Separar motivos de mudança já organiza muito o código e prepara o terreno para os outros princípios. Se você aplicar bem só esse, com classes e funções que fazem uma coisa só, já colhe grande parte do benefício.
- O que é a inversão de dependência na prática?
- É fazer o código de alto nível depender de uma abstração, uma interface, em vez de uma implementação concreta. Assim você injeta a implementação que quiser: um banco real na produção, um dublê em memória nos testes. Isso desacopla as peças e torna o sistema flexível e testável.
- SOLID conflita com a simplicidade que o Python valoriza?
- Pode conflitar se aplicado em excesso. O Python valoriza soluções simples e diretas, e SOLID mal usado gera abstração demais. A chave é equilíbrio: aplique os princípios onde eles reduzem dor de manutenção real, e prefira o código simples quando a flexibilidade extra não vai ser usada.
Fontes
Seu progresso fica salvo neste aparelho. Assinantes sincronizam entre os aparelhos.