Regra
Aulas devem ter responsabilidade responsabilidade.
As classes que lidam com várias preocupações viola
o Responsabilidade Princípio .
Idiomas suportados: JS, TS, PY, JAVA, C/C++,
C#, Swift/Objective C, Ruby. PHP, Kotlin,
Scala, Rust, Haskell, Groovy, Dart. Julia,
Elixit, Klojure, OCaml, DelphiIntrodução
Classes que fazem demais tornam-se gargalos. Uma classe que lida com autenticação, e-mails e validação exige mudanças sempre que qualquer preocupação evolui, arriscando quebras em funcionalidades não relacionadas. Testar exige a simulação (mocking) da classe inteira, mesmo ao testar apenas um aspecto. O Princípio da Responsabilidade Única afirma que uma classe deve ter apenas uma razão para mudar.
Por que isso importa
Manutenibilidade do código: Classes com múltiplas responsabilidades mudam com mais frequência porque a evolução de qualquer preocupação afeta a classe inteira.
Complexidade de teste: Testar classes com múltiplas responsabilidades exige o mocking de todas as dependências, mesmo para testar uma única funcionalidade.
Reutilização: Não é possível extrair uma responsabilidade sem trazer todas as dependências. Desenvolvedores duplicam código em vez de desvincular classes com múltiplas responsabilidades.
Coordenação da equipe: Múltiplos desenvolvedores trabalhando na mesma classe para diferentes funcionalidades criam conflitos de merge frequentes. Classes de responsabilidade única permitem o desenvolvimento paralelo sem conflitos.
Exemplos de código
❌ Não-conforme:
class UserManager {
async createUser(userData) {
const user = await db.users.insert(userData);
await this.sendWelcomeEmail(user.email);
await this.logEvent('user_created', user.id);
await cache.set(`user:${user.id}`, user);
return user;
}
async sendWelcomeEmail(email) {
const template = this.loadEmailTemplate('welcome');
await emailService.send(email, template);
}
async logEvent(event, userId) {
await analytics.track(event, { userId, timestamp: Date.now() });
}
}
Por que está errado: Esta classe lida com operações de banco de dados, envio de e-mail, logging e caching. Alterações em templates de e-mail, formatos de logging ou estratégia de cache exigem a modificação desta classe. Testar a criação de usuários significa simular serviços de e-mail, analytics e cache, tornando os testes lentos e frágeis.
✅ Compatível:
class UserRepository {
async create(userData) {
return await db.users.insert(userData);
}
}
class EmailNotificationService {
async sendWelcomeEmail(email) {
const template = await this.templateLoader.load('welcome');
return await this.emailSender.send(email, template);
}
}
class UserEventLogger {
async logCreation(userId) {
return await this.analytics.track('user_created', {
userId,
timestamp: Date.now()
});
}
}
class UserService {
constructor(repository, emailService, eventLogger, cache) {
this.repository = repository;
this.emailService = emailService;
this.eventLogger = eventLogger;
this.cache = cache;
}
async createUser(userData) {
const user = await this.repository.create(userData);
await Promise.all([
this.emailService.sendWelcomeEmail(user.email),
this.eventLogger.logCreation(user.id),
this.cache.set(`user:${user.id}`, user)
]);
return user;
}
}
Por que isso importa: Cada classe tem uma responsabilidade clara: persistência de dados, envio de e-mail, registro de eventos ou orquestração. Alterações nos modelos de e-mail afetam apenas EmailNotificationService. O teste de criação de usuário pode usar stubs simples para dependências. As classes podem ser reutilizadas independentemente em diferentes funcionalidades.
Conclusão
O Princípio da Responsabilidade Única não é sobre tornar as classes o menor possível, é sobre garantir que cada classe tenha uma razão clara para mudar. Quando uma classe começa a lidar com múltiplas preocupações, refatore extraindo cada responsabilidade para sua própria classe com uma interface focada. Isso torna o código mais fácil de testar, manter e evoluir sem mudanças em cascata em funcionalidades não relacionadas.
.avif)
