O princípio da responsabilidade única
("toda classe deve ter apenas uma única responsabilidade; em outras palavras, toda classe deve ter um e apenas um motivo para mudar")
Discordo. Eu acho que um método deve ter apenas um motivo para mudar, e todos os métodos em uma classe devem ter um relacionamento lógico entre si , mas a própria classe pode realmente fazer várias coisas (relacionadas).
Na minha experiência, esse princípio muitas vezes é aplicado com zelo demais, e você acaba com muitas pequenas classes de método único. As duas lojas ágeis em que trabalhei fizeram isso.
Imagine se os criadores da API .Net tivessem esse tipo de mentalidade: em vez de List.Sort (), List.Reverse (), List.Find () etc., teríamos as classes ListSorter, ListReverser e ListSearcher!
Em vez de argumentar mais contra o SRP (o que em si não é terrível em teoria) , vou compartilhar algumas de minhas experiências anedóticas há muito tempo:
Em um local em que trabalhei, escrevi um solucionador de fluxo máximo muito simples que consistia em cinco classes: um nó, um gráfico, um criador de gráficos, um solucionador de gráficos e uma classe para usar o criador / solucionador de gráficos para resolver um problema. problema do mundo real. Nenhuma era particularmente complexa ou longa (o solucionador era de longe o mais longo, com ~ 150 linhas). No entanto, foi decidido que as classes tinham muitas "responsabilidades", então meus colegas de trabalho começaram a refatorar o código. Quando terminaram, minhas 5 classes foram expandidas para 25, cujas linhas de código totais eram mais do que o triplo do que eram originalmente. O fluxo do código não era mais óbvio, nem era o objetivo dos novos testes de unidade; Agora eu tinha dificuldade em descobrir o que meu próprio código fazia.
No mesmo local, quase todas as classes tinham apenas um único método (sua única "responsabilidade"). Seguir o fluxo dentro do programa era quase impossível, e a maioria dos testes de unidade consistia em testar se essa classe chamava código de outra classe , cujo objetivo era igualmente um mistério para mim. Havia literalmente centenas de classes onde deveria haver (IMO) apenas dezenas. Cada classe fez apenas uma "coisa" , mas mesmo com convenções de nomenclatura como "AdminUserCreationAttemptorFactory" , era difícil distinguir o relacionamento entre as classes.
Em outro lugar (que também tinha a mentalidade de que as classes deveriam ter apenas um método ), estávamos tentando otimizar um método que ocupava 95% do tempo durante uma determinada operação. Depois de (um tanto estupidamente) otimizá-lo um pouco, voltei minha atenção para o motivo de ser chamado de bajilhão de vezes. Ele estava sendo chamado em um loop em uma classe ... cujo método estava sendo chamado em um loop em outra classe .. que também estava sendo chamado em um loop ..
Ao todo, havia cinco níveis de loops espalhados por 13 classes (sério). O que qualquer classe realmente estava fazendo era impossível de determinar apenas olhando para ela - você tinha que esboçar um gráfico mental de quais métodos ela chamava e de quais métodos esses métodos chamavam, e assim por diante. Se tudo tivesse sido agrupado em um método, teria apenas cerca de 70 linhas com o nosso método-problema aninhado dentro de cinco níveis de loops imediatamente óbvios.
Meu pedido para refatorar essas 13 classes em uma classe foi negado.