DEV Community

Yuri Peixinho
Yuri Peixinho

Posted on

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

Single Responsability Principle

Esse é o primeiro pilar do SOLID. A definição clássica é “Uma classse deve ter um, e apenas um motivo pra mudar.”.

Na prática, isso quer dizer que uma classe deve ser responsável por uma funcionalidade/parte específica do software. Em sistemas “blocos de cimentos”, é comum encontrarmos as chamadas “God Objects” (Objeto Deus), uma classe gigantesca que sabem e fazem tudo. O que contradiz o princípio da responsabilidade única.

Analogia

Imagine um funcionário de um restaurante que é, ao mesmo tempo, o cozinheiro, o garçom e o faxineiro . Se ele precisar mudar a forma como limpa o chão, o serviço de cozinha e o atendimento podem ser afetados ou interrompidos. No SRP, dividimos essas tarefas entre especialistas para que um não atrapalhe a evolução do outro.

Exemplo

Vamos imaginar um cenário em que o princípio não foi aplicado e após isso vamos transformá-lo em um código modular. Imagine um sistema que gerencia pedidos de e-commerce.

Exemplo Problema

Na classe Pedido abaixo, temos três motivos diferentes para serem alterados. Se a regra de calculo, banco e e-mail mudar. Cada método representa uma responsabilidade diferente para a classe Pedido

class Pedido:
    def calcular_total(self):
        # Lógica de negócio (Preço, impostos, descontos)
        pass

    def salvar_no_banco(self):
        # Lógica de infraestrutura (Conexão SQL, tabelas)
        pass

    def enviar_email_confirmacao(self):
        # Lógica de comunicação (Servidor SMTP, template do e-mail)
        pass
Enter fullscreen mode Exit fullscreen mode

Exemplo Solução

Para aplicar o SRP, separamos as tarefas em “especialistas”. Cada classe agora tem apenas uma razão para existir e mudar.

  1. Pedido vai conter apenas a lógica de cálculo calcular_total
  2. salvar_no_banco vai ser uma nova classe chamada PedidoRepository, que vai implementar o Padrão Repository
  3. enviar_email_confirmacao vai ser um serviço separado apenas por enviar comunicações

Desse modo, se você decidir trocar o e-mail por uma mensagem no WhatsApp, você altera apenas o serviço respectivo. A regra de cálculo do Pedido então permanece segura e intocada, como uma peça LEGO independente

Exemplo aplicado a contexto: Clean Architecture, Mediator, CQRS e DDD

Veja como o SRP se manifesta em um CommandHandler usando Mediator:

// Este Handler tem UMA única razão para mudar: 
// Se o fluxo de "Criação de Pedido" for alterado.
public class CriarPedidoHandler : IRequestHandler<CriarPedidoCommand, Guid>
{
    private readonly IPedidoRepository _repository; // Interface (DIP)
    private readonly IMediator _mediator;

    public async Task<Guid> Handle(CriarPedidoCommand request, CancellationToken ct)
    {
        // 1. Regra de Negócio (DDD: Entidade decide se pode ser criada)
        var pedido = new Pedido(request.ClienteId, request.Itens);

        // 2. Persistência (Clean Arch: O Handler não sabe se é SQL ou NoSQL)
        await _repository.SalvarAsync(pedido);

        // 3. Comunicação (Mediator: Dispara um evento para quem interessar)
        // Isso separa a criação do pedido do envio de e-mail (SRP puro!)
        await _mediator.Publish(new PedidoCriadoEvent(pedido.Id));

        return pedido.Id;
    }

Enter fullscreen mode Exit fullscreen mode

Veja o conteúdo completo aqui!

Top comments (0)