Boas práticas e padrões · Princípios SOLID · 5 min de leitura
S — Princípio da responsabilidade única (SRP)
Uma classe deve ter um só motivo para mudar: cada parte do código responde a um único "dono" da regra.
Arraste para o lado para ver o diagrama inteiro.
O que diz
Robert C. Martin resume: "reúna o que muda pelos mesmos motivos e separe o que muda por motivos diferentes". "Responsabilidade" não é "fazer uma coisa só", e sim responder a um único ator: o financeiro muda a regra do preço, o DBA muda a persistência, o marketing muda o e-mail.
Como perceber a violação
- A classe tem muitos imports de áreas diferentes (HTTP, SQL, e-mail, PDF…).
- Mudanças de times diferentes caem sempre no mesmo arquivo e geram conflitos de merge.
- Para testar um cálculo você precisa subir banco e servidor de e-mail.
Na prática
Extraia cada responsabilidade para uma classe com nome claro e deixe uma classe coordenadora fina (um caso de uso) chamando as três. Não exagere: dividir uma classe de 40 linhas em dez arquivos só aumenta o custo de leitura.
No código: antes e depois
class PedidoService(private val db: Database, private val smtp: Smtp) {
fun fechar(pedido: Pedido) {
// regra do financeiro
val total = pedido.itens.sumOf { it.preco * it.qtd } * 0.95
// regra do banco
db.execute("UPDATE pedidos SET total = ? WHERE id = ?", total, pedido.id)
// regra do marketing
smtp.send(pedido.email, "Pedido fechado: R$ $total")
}
} class CalculadoraPreco { fun total(p: Pedido) = p.itens.sumOf { it.preco * it.qtd } * 0.95 }
interface PedidoRepository { fun salvarTotal(id: Long, total: Double) }
interface Notificador { fun pedidoFechado(p: Pedido, total: Double) }
class FecharPedido(
private val preco: CalculadoraPreco,
private val repo: PedidoRepository,
private val avisar: Notificador,
) {
operator fun invoke(p: Pedido) {
val total = preco.total(p)
repo.salvarTotal(p.id, total)
avisar.pedidoFechado(p, total)
}
} O caso de uso FecharPedido só coordena. A regra de preço é testada sozinha, e trocar SMTP por push não toca no cálculo.
Em resumo
- Um motivo para mudar = um ator que pede a mudança.
- Separa testes: o cálculo é testado sem banco nem e-mail.
- Reduz conflitos de merge entre times.
- Classe coordenadora fina + classes especialistas.
Vantagens e custos
- Código mais fácil de testar e de entender.
- Mudanças localizadas, menos efeitos colaterais.
- Mais arquivos e indireção.
- Dividir cedo demais cria abstrações sem uso.