Não há uma resposta clara para isso. Embora a pergunta seja estreita, as explicações não são.
Para mim, é algo como o Navalha de Occam, se você quiser. É um ideal onde eu tento medir meu código atual. É difícil identificá-lo com palavras claras e simples. Outra metáfora seria "um tópico" que é tão abstrato, isto é, difícil de entender, como "responsabilidade única". Um terceiro descritor seria "lidar com um nível de abstração".
O que isso significa praticamente?
Ultimamente eu uso um estilo de codificação que consiste principalmente de duas fases:
A fase I é melhor descrita como caos criativo. Nesta fase, escrevo o código à medida que os pensamentos fluem - ou seja, cru e feio.
A fase II é o oposto completo. É como limpar depois de um furacão. Isso exige mais trabalho e disciplina. E então eu olho para o código da perspectiva de um designer.
Atualmente, estou trabalhando principalmente em Python, o que me permite pensar em objetos e classes posteriormente. Primeira Fase I - Escrevo apenas funções e as espalho quase aleatoriamente em diferentes módulos. Na Fase II , depois que eu comecei as coisas, tenho uma visão mais detalhada de qual módulo lida com qual parte da solução. E, enquanto percorre os módulos, os tópicos são emergentes para mim. Algumas funções estão relacionadas tematicamente. Estes são bons candidatos para as aulas . E depois que transformei funções em classes - o que é quase feito com recuo e adição self
à lista de parâmetros em python;) - uso SRP
como o Razcam da Occam para remover a funcionalidade de outros módulos e classes.
Um exemplo atual pode estar escrevendo uma pequena funcionalidade de exportação no outro dia.
Havia a necessidade de csv , excel e folhas de excel combinadas em um zip.
A funcionalidade simples foi realizada em três visualizações (= funções). Cada função usava um método comum para determinar filtros e um segundo método para recuperar os dados. Em cada função, a preparação da exportação ocorreu e foi entregue como uma resposta do servidor.
Havia muitos níveis de abstração misturados:
I) lidar com solicitação / resposta de entrada / saída
II) determinação de filtros
III) recuperando dados
IV) transformação de dados
O passo fácil foi usar uma abstração ( exporter
) para lidar com as camadas II-IV em um primeiro passo.
O único restante foi o tópico que lida com solicitações / respostas . No mesmo nível de abstração está extraindo parâmetros de solicitação, o que é bom. Então, eu tinha para essa visão uma "responsabilidade".
Segundo, tive que dividir o exportador, que, como vimos, consistia em pelo menos três outras camadas de abstração.
A determinação dos critérios de filtro e a recuperação real estão quase no mesmo nível de abstração (os filtros são necessários para obter o subconjunto correto dos dados). Esses níveis foram colocados em algo como uma camada de acesso a dados .
Na próxima etapa, dividi os mecanismos de exportação reais: onde era necessário gravar em um arquivo temporal, dividi-o em duas "responsabilidades": uma para a gravação real dos dados no disco e outra parte que tratava do formato real.
Ao longo da formação das classes e módulos, as coisas ficaram mais claras, o que pertencia a onde. E sempre a pergunta latente, se a classe faz demais .
Como você determina quais responsabilidades cada classe deve ter e como define uma responsabilidade no contexto do SRP?
É difícil dar uma receita a seguir. É claro que eu poderia repetir a regra enigmática "um nível de abstração" - se isso ajudar.
Principalmente para mim, é um tipo de "intuição artística" que leva ao design atual; Eu modelo código como um artista pode esculpir argila ou pintar.
Imagine-me como um codificador Bob Ross ;)