Princípio da Responsabilidade Única

Princípio da Responsabilidade Única (Single Responsability Principle)

O Princípio da Responsabilidade Única dita que uma classe deve ter apenas uma, e apenas uma só, responsabilidade.

Quando a classe tem mais de uma responsabilidade ela se torna dificil de manter porque o código de uma responsabilidade começa a interferir com a manutenção do código das outras responsabilidades.

O termo "responsabilidade" não significa "funcionalidade", e tão pouco significa "método". O Princípio da Responsabilidade Única não significa que a classe só deve ter um método, ou só deve ter uma função, ou apenas fazer uma coisa. O Princípio da Responsabilidade Única significa que a classe deve tomar controle se todas as funcionaldiades que dizem respeito à mesma responsabilidade e apenas essas.

Tomemos como exemplo uma classe chamada Rational. Qual diriamos que é a sua responsabilidade? A responsabilidade de Rational é modelar um número racional. O Princípio da Responsabilidade Única nos diz, então, que Rational não pode conter funcionalidades que não sejam relacionadas ao que um número racional é. E, deve, por outro lado, conter todas as funcionalidades relacionadas ao que um número racional é.

A classe Rational deve ter uma forma de representar números racionais em memória. Deve ser possível obter o numerador e denominador do número racional. Deve proporcionar operações aritméticas. Repare que a classe provê funcionalidades diferentes, mas todas elas relacionadas ao que esperamos ser possível fazer com um número rational.

Podemos ter métodos na classe que formatam o número racional para e de uma string? Pelo Princípio da Responsabilidade Única não. Formatação não é uma capacidade natural de um número racional. Nunca nas aulas de matemática se ouvi falar de formatar um racional. A formatação deve, pois, ser deixada para outra classe.

God Object

Quando uma classe não cumpre com o Princípio da Responsabilidade Única ela vai acumulando responsabilidades. Conforme ela acumular responsabilides o código vai usando-a cada vez mais, mas o código interno da classe começa a ficar mais complicado, com métodos e estado que não têm correlação.

Criar uma classe assim, com várias responsabilidades é um anti-padrão conhecido como God Object (Objeto deus).

Sinais de Desvio do Princípio

O primeiro sinal de desvio é quando a classe têm muitos atributos que não se relacionam entre si. Que não formam uma unidade. Isto costuma ser um sinal de que a classe tem várias responsabilidades diferentes e, por isso, precisa manter estados para cada uma delas.

Outro sinal de desvio é quando a classe têm métodos que não se correlacionam com o conceito da classe no mundo real. Ter alguns métodos utilitários para ajudar na escrita do código, pode ser útil, mas definir a qual classe corresponde o método é essencial para não violar o Princípio da Responsabilidade Única. Por exemplo, poderiamos pensar que não ha mal em colocar um método na classe Rational que cria um número complexo.

class Rational {
 ...

 Complex toComplex(){
   return new Complex(this, 0);
}

...

Este método constroi um objeto Complex usando o valor da classe Rational com a parte real. Parece inofensivo, mas a classe Rational acabou de ganhar a responsabilidade de ser uma fábrica de números complexos. E se o número racional tivesse que ser a parte imaginária? Poderiamos alterar para:

class Rational {
 ...

 Complex toRealComplex(){
   return new Complex(this, 0);
}
 Complex toImaginaryComplex(){
   return new Complex(0, this);
}

...

Poderia pareceer muito evidente e até interligente fazermos esta escolha e design e tornar a classe Rational uma fábrica de objetos Complex, mas estariamos violando o Princípio da Responsabilidade Única.

A forma de ver que estamos violando é levar a decisão ao extremo. Decidimo que não faz mal que Rational seja uma fábrica de objetos Complex, mas e se tivessmos mais objetos para criar? Teriamos um método para cada um? Claramente não. Então, se não faz sentido para muitos, não faz sentido para um. Não ha exceções. Não ha "mas é só este…​".

Seguir o Princípio da Responsabilidade Única nos obrigaria a remover esses métodos dali e chegar num melhor design em que a classe Complex tem os métodos para criar instancias a partir de Rational. Sem a trava do Princípio da Responsabilidade Única, não iriamos procurar por outro design melhor. Por isso é importante seguir o Princípio da Responsabilidade Única em todas as classes que constroi.

Rational é um objeto de valor e pode ser óbvio que um objeto de valor deve ser apenas isso: um valor. Para objetos mais complexos como serviços, repositórios e telas seguir o Princípio da Responsabilidade Única pode não ser tão obvio. Lembre-se que o Princípio da Responsabilidade Única não limita o número de métodos, operações ou atributos na sua classe. Ele limita a responsabilidade da classe.

Origem Histórica

O termo foi cunhado por Robert C. Martin em um artigo escrito em 2003 e depois popularizado no seu influente livro "Agile Software Development, Principles, Patterns, and Practice" em 2005. Mais tarde em 2014 ele escreveu um artigo no seu blog refinando o conceito.

Também pela mão de Robert C. Martin este princípio entrou para o top 5 dos Principios de Orientação de Objetos, juntos conhecidos como os "Principios SOLID" (SOLID Principles) num trocadilho de palavras sugerindo que seguir os princípios SOLID, tornaria o código sólido, por oposição a frágil. O Princípio da Responsabilidade Única corresponde ao S pelo seu nome em inglês: Single Responsability Principle.

Robert C. Martin conecta o conceito de "responsabilidade" com "uma razão para reescrever o código da classe". Esta metáfora não é das mais claras e leva os programadores a considerar que o princípio fala de métodos e detalhes de implementação, quando o conceito é realmente abstrato e tem que com a responsabiliade relacionada da classe, o foco é o porquê dessa classe ter esses métodos e não como são implementados.

Scroll to Top