Executando verificação de segurança...
7

[SOLID] Single Responsability Principle

De todos os princípios SOLID, o SRP provavelmente é o mais conhecido e o menos compreendido. Isso se deve principalmente ao seu nome inadequado. Ao escutar esse nome, logo pensamos que os módulos devem fazer apenas uma coisa.

O Que É Esse Tal de SRP?

O SRP diz basicamente: "Um módulo deve ter uma, e apenas uma, razão para mudar".

O Problema: A Classe Canivete Suíço

Imagine que você está no escritório e encontra esta belezinha no código:

<?php
class Funcionario {
    private $nome;
    private $salario;

    public function calcularSalario() {
        // 50 linhas de lógica complexa aqui
    }

    public function salvarNoBanco() {
        // Conexão com banco, SQL, transactions...
    }

    public function enviarEmail() {
        // SMTP, templates, validações...
    }

    public function gerarRelatorio() {
        // PDF, formatação, headers...
    }

    public function validarCPF() {
        // Algoritmo de validação de CPF
    }
}
?>

Esta classe Funcionario está fazendo mais coisas que um estagiário no primeiro dia: calculando salário, salvando no banco, enviando email, gerando relatório E validando CPF. É o Batman do código, mas sem a parte legal de ser herói.

Por Que Isso É Um Problema?

1. O Pesadelo dos Múltiplos Motivos Para Mudar

Nossa classe Funcionario tem pelo menos 5 motivos diferentes para ser alterada:

  • Mudança nas regras de cálculo salarial → mexe na classe
  • Troca do banco de dados → mexe na classe
  • Novo template de email → mexe na classe
  • Mudança no formato do relatório → mexe na classe
  • Nova validação de CPF → mexe na classe

Quando a regra de negócio exige mudança no cálculo do vale-refeição, você acaba mexendo em código que envia email, e de repente os relatórios param de funcionar.

2. Teste Vira Pesadelo

Tentar testar essa classe é como tentar usar óculos de grau emprestado: tecnicamente funciona, mas você sai com dor de cabeça. Você quer testar apenas o cálculo de salário, mas precisa mockar banco de dados, servidor de email e impressora PDF. É mais setup que o Arch Linux.

3. Reutilização? Esquece!

Quer usar só a validação de CPF em outro lugar? Paciência, meu amigo, você vai ter que carregar toda a bagagem da classe Funcionario nas costas, como quem viaja de ônibus com mala de rodinha quebrada.

A Solução: Separar Para Conquistar

Vamos aplicar o SRP e transformar nossa classe Frankenstein em algo mais civilizado:

<?php
// Apenas dados do funcionário
class Funcionario {
    public function __construct(
        private readonly string $nome,
        private readonly int $salario,
    ) {}
}

// Especialista em cálculos
class CalculadoraSalario {
    public function calcular(Funcionario $funcionario) {
        // Lógica de cálculo aqui
    }
}

// Especialista em persistência
class RepositorioFuncionario {
    public function salvar(Funcionario $funcionario) {
        // Lógica de banco aqui
        // PDO, Eloquent, ou o que preferir
    }
}

// Especialista em comunicação
class ServicoEmail {
    public function enviar($destinatario, $assunto, $corpo) {
        // Lógica de email aqui
        // PHPMailer, SwiftMailer, etc.
    }
}

// Especialista em relatórios
class GeradorRelatorio {
    public function gerar(array $funcionarios) {
        // Lógica de relatório aqui
        // TCPDF, DomPDF, etc.
    }
}

// Especialista em validação
class ValidadorCPF {
    public function validar($cpf) {
        // Lógica de validação aqui
    }
}
?>

Agora sim! Cada classe tem sua especialidade, como um time de super-heróis onde cada um tem seu poder específico, ao invés de um Homem-Aranha que também é médico, advogado e professor de culinária.

Os Benefícios de Seguir o SRP

1. Manutenção Mais Fácil

Precisa alterar como o salário é calculado? Vai direto na CalculadoraSalario. Precisa mudar o template do email? ServicoEmail te espera. É como ter uma caixa de ferramentas organizada, ao invés de uma gaveta bagunçada.

2. Testes Mais Simples

Testar a CalculadoraSalario agora é moleza: passa um Funcionario, chama o método, verifica o resultado. Sem mock de banco, sem configuração de SMTP, sem dor de cabeça.

3. Reutilização Real

O ValidadorCPF pode ser usado em qualquer lugar que precise validar CPF: cadastro de clientes, fornecedores, ou até no seu projeto paralelo da loja de açaí.

4. Entendimento Mais Rápido

Quando alguém novo chega no time e precisa entender o código, é muito mais fácil explicar: "Essa classe calcula salário, essa salva no banco, essa envia email..." do que "Essa classe faz... bem... tudo."

Cuidado Com os Exageros

Como tudo na vida, o SRP pode ser levado ao extremo. Não é para criar uma classe para cada linha de código:

<?php
// Isso aqui é exagero, galera
class SomadorDeUm {
    public function somar($numero) {
        return $numero + 1;
    }
}
?>

O segredo é encontrar o equilíbrio. Pense no SRP como uma dieta: o objetivo é ser saudável, não passar fome.

Sinais de Que Você Está Violando o SRP

  • Sua classe tem mais métodos públicos que um canivete suíço tem ferramentas
  • Você usa "E" frequentemente ao explicar o que a classe faz: "Ela calcula salário E envia email E gera relatório E..."
  • Suas classes têm nomes genéricos demais: Manager, Handler, Utils, Helper (especialmente se elas fazem mais que gerenciar, manusear, ou ajudar)
  • Quando você precisa alterar um requisito simples, acaba mexendo em 15 métodos diferentes da mesma classe

Conclusão

O Princípio da Responsabilidade Única não é sobre criar milhões de classes minúsculas, mas sobre criar código que faça sentido, seja fácil de manter e não dê vontade de chorar toda vez que você precisa fazer uma alteração.

Lembre-se: código bom é como uma boa piada - se você precisa explicar muito, provavelmente não está tão bom assim. E se sua classe precisa de um manual de instruções para ser entendida, talvez seja hora de aplicar um pouco de SRP na sua vida.

Carregando publicação patrocinada...
2

Uma boa diretriz sobre este princípio - até escrito pelo próprio Bob é: "A quem as alterações respondem". Então dependerá muito do produto e estrutura da empresa. É mais sobre isto do que como você falou, quebrar em pequnas classes.

who is the program responsible to? Better yet: who must the design of the program respond to?

The Single Responsibility Principle

1
-1

Interessante como o post é uma tentativa de mostrar como o SRP é útil mas acaba com o efeito contrário, igual a todos os outros posts/vídeos que tentam mostrar como o princípio melhora o código.

Primeiramente, o exemplo é muito pequeno. Pegar uma classe fora de contexto não tem utilidade para demonstrar como melhorar o código. Não tem como saber como o código está sendo realmente utilizado, só mostra a classe, cadê o código que faz uso dessa classe? Como que mudar o código de cálculo de VR afeta os relatórios? Cadê a "tentativa" de testes pra mostrar como é difícil? Mockar o banco seria a única forma de testar esse código? (Spoiler: não é.) Se existe apenas essa classe, então nenhum dos "problemas" citados fazem sentido. Mesmo que fosse parte de um projeto maior, ainda assim nenhum dos "problemas" são realmente problemas.

  1. O Pesadelo dos Múltiplos Motivos Para Mudar

E daí que tem múltiplos motivos pra mudar? Se mudar o cálculo do VR afeta os relatórios então não é um problema de estar tudo junto na classe mas um problema muito pior de acoplamento de duas funcionalidades que não tem nenhum relacionamento. Caso a lógica do relatório faz uso do cálculo do VR, então a solução não seria separar em classes utilizando SRP, seria deixar na mesma classe porque ficaria mais fácil fazer essa mudança.

  1. Teste Vira Pesadelo

Teste não vira pesadelo, você precisa testar de forma automatizada o que dá pra automatizar. Testar impressora e email são testes manuais mesmo. Não é um problema de estar tudo junto na mesma classe. Além disso você não precisa mockar nada, se você vai testar o calcularSalario, não é necessário nenhuma conexão com banco ou impressora.

$f = new Funcionario("felprangel", 0);
if($f->calcularSalario() == 0) // teste passou
  1. Reutilização? Esquece!

Não há nada que obrigue você a utilizar a classe Funcionario, nesse caso você simplemente extrai essa validação para uma função e pronto. Caso essa validação de CPF apenas ocorra nessa classe, não há nenhum necessidade de extrair para reutilizar já que não é reutilizado em nenhuma outra parte do código.

O Princípio da Responsabilidade Única não é sobre criar milhões de classes minúsculas

Mas a solução que você dá cria "milhões" de classes minúsculas...

Entendo que separar coisas distintas é uma forma boa de organizar, mas a solução proposta é muito ruim. Se fosse por um lado mais OO, a forma que faz mais sentido seria assim:

// funcionario.php
class Funcionario {
    string $nome;
    int $salario;

    // Funções relacionadas ao funcionário
    function calcularSalario() {} // Não precisa passar funcionário com argumento
    function salvarNoBanco() {}
    function gerarRelatorio() {} // A listagem geralmente pega do banco mesmo, então não faria sentido passar um array como parametro, faz a chamada do banco aqui mesmo, sem nenhum argumento.
}

// Aqui acho desnecessário o uso de classes até mesmo pra código OO já que PHP tem essa opção, diferente de Java.
// cpf.php
function validar_cpf() {}

// email.php
function enviar_email() {}

Se fosse por um lado mais procedural (que eu prefiro) seria assim:

// funcionario.php
class Funcionario {}

function calcularSalario(Funcionario $f) {}
function salvarFuncionarioNoBanco(Funcionario $f) {}
function gerarRelatorioDeFuncionarios(Funcionario $f) {}

// O resto igual a versão de cima.

Conclusão

O código "problemático" na verdade não tem nenhum problema. SRP é uma ideia genérica e abstrata que não ajuda em nada, apesar das afirmações das pessoas que a defendem.