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.
- 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.
- 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
- 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.