Arquitetura de SoftwareProgramação

S.O.L.I.D na prática: Single Responsibility Principle (SRP)

Neste post veremos o Princípio da Responsabilidade Única ou Single Responsibility Principle (SRP):

Esse é o segundo post da série sobre os 5 princípios SOLID, que é um conjunto de princípios da Programação Orientada a Objetos (POO) estabelecidos por Robert C. Martin, também conhecido como Uncle Bob.

Se quiser entender melhor sobre as principais motivações de compreendermos estes princípios e ter a visão geral sobre essa série de posts, acesse o primeiro artigo da série pelo link a seguir:

Clique aqui caso queira acessar o primeiro post da série sobre SOLID

O Princípio da Responsabilidade Única diz que:

Um módulo deve ter uma, e apenas, uma razão para mudar

Robert C. Martin (Uncle Bob)

O autor Uncle Bob, em seu livro Clean Architecture, define módulo como “um conjunto coeso de estruturas de dados e funções”. Nesse contexto de sistemas orientados a objetos, normalmente associamos um módulo como uma Classe.

O objetivo então é recomendar que não deveríamos propor uma Classe que tenha mais de um motivo de negócio para ser alterada, pois essas alterações podem ser conflitantes e isso pode comprometer (e muito) as funcionalidades em questão.

“Quando for organizar seus módulos (classes, métodos…), não se esqueça dos ATORES caro dev reflexivo” 😀

(Outro dev reflexivo)

O autor, também complementa que: “um módulo deve ser responsável por um, e apenas um ator e recomenda separar o código no qual esses “atores” dependam.

Na prática, podemos entender um “ator“, como uma pessoa ou um grupo de pessoas com um papel de negócio bem definido em um contexto, por exemplo, pessoas de um determinado setor ou de um determinado departamento ou projeto. Neste caso pessoas de escopos diferentes podem ser consideradas como atores diferentes.

Imagine um cenário em que uma classe e/ou método possuem uma método/função com regras compartilhadas entre 2 setores de uma empresa. Neste caso a classe que, contém essas regras, sofrerá alteração para atender a nova necessidade do setor 1. Imagine agora que essa alteração não deva ser aplicada para o setor 2 pois irá gerar um impacto na operação… Como a regra e comportamentos (métodos) estão na mesma classe, teremos um sério problema.

Ainda que muitos possam pensar em criar alguns tratamentos ou desvios (Ifs, Elses, switchs, etc.) no código para resolver tal questão, pense que, sempre que houver uma alteração nessa classe os 2 setores estarão expostos ao risco dessa alteração. No exemplo o vídeo a seguir, mostro essa situação.

Logo, podemos entender também que uma Classe não deveria conter regras e funcionalidades que serão impactadas por esses papéis diferentes, porque normalmente eles terão motivações de negócio distintas (se não agora, provavelmente em um futuro próximo).

Dessa forma, uma vez que o SRP é violado, torna-se comum que problemas possam começar a surgir, tais como:

  • Dificuldade de entendimento e manutenção no código;
  • Falta de coesão ou baixa coesão no design de código das classes do projeto. Isso significa que uma ou mais classes podem estar com responsabilidades incoerentes, normalmente tendo que lidar com mais coisas do que deveria;
  • Dificuldade ou até mesmo a inviabilidade para implementar testes automatizados. Quanto mais confuso e incoerente for o código, mais difícil será testá-lo, criar mocks, manter o sistema “testável“, e assim por diante…. Nem preciso dizer que com menos testes também será afetada a garantia de qualidade do software, não é mesmo?

No vídeo a seguir, reforço sobre esses conceitos e mostro exemplos com 2 casos, cada um com 2 situações, uma situação de violação e outra de adequação ao SRP.

Um cuidado adicional ao analisar a “Responsabilidade única”

Podemos pensar que esse princípio é relativamente simples de se compreender, mas por esse mesmo motivo, também pode esconder algumas pegadinhas…

Uma confusão comum que ocorre no entendimento e aplicação do SRP é que pode haver a tendência de desenvolvedores associarem a expressão “responsabilidade única” de forma a considerar apenas o aspecto de isolar e organizar as classes e métodos em arquivos-fonte distintos e classificá-los somente conforme a sua própria visão ou a visão do time de devs. Assim pode estar dando menos relevância as operações e aos atores do negócio em si. Em muitos casos podem até desconhece-los ou estarem ignorando os reais papeis desempenhados pelos usuários no sistema.

Na prática esses dois aspectos muitas vezes podem acabar se misturando e por isso gerar esse tipo de confusão, embora a organização dos arquivos-fonte também seja algo importante, é sempre bom lembrarmos que o objetivo principal não é apenas distinguir classes ou os métodos em si, mas sim a estruturação de regras e comportamentos de forma que estejam coerentes com as operações do negócio em questão e claro com menor risco possível na execução.

Nem sempre teremos disponíveis todas as informações, documentações e apoio necessários para realizar um trabalho mais minucioso e conhecer certos detalhes, mas isso também não deve impedir nossa busca pela revisão e evolução constante do código e de certas práticas aplicadas nos times e no negócio.

Enfim, a provocação que eu quis deixar aqui é apenas para reforçar a principal recomendação e intenção do SRP para nos atentarmos um pouco mais sobre questões como essa durante os processos de estruturação ou refatoração do design de código.

Vale lembrar também que outros conceitos e práticas como o Clean code e técnicas de refatoração também ajudarão muito nesse tipo de trabalho.

Por hora é isso, obrigado por ler e/ou assistir o conteúdo até aqui. 😉
Até a próxima e vamos juntos! \o/

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *