Sumário
Veja o índice completo do tópico “S.O.L.I.D”
Olá pessoas …
Dando início a nossa saga de artigos, vamos iniciar com a primeira letra do acróstico, S que define a sigla SRP Single Responsibility Principle (Princípio da Responsabilidade Única).
Definição
Isto quer dizer que nossas classes devem ter apenas uma, e somente uma, razão para ser modificada. Se a classe possuir mais de um motivo para ser modificada, a mesma não é coesa e isso já fere os princípios da POO (Programação Orientada à Objetos).
Problemas ao ferir o primeiro princípio.
- Dificuldade de compreensão, logo dificuldade de manutenção na classe;
- Não permite reuso;
- Alto acoplamento, a classe depende de conhecer outras e outras e mais outras classes para poder funcionar, o que dificulta a manutenção ao alterar as classes de dependência;
Imaginem um canivete suíço, para quem não sabe, é este ai abaixo, o pai dos canivetes suíços.
Canivete criado por John S. Holler por volta de 1880, na Alemanha e possui 100 funções.
As tampinhas só foram inventadas em 1891. Fonte: Google
Este canivete, se fosse uma aplicação, fere completamente o primeiro princípio. O da responsabilidade única. Em nossas aplicações cada objeto deve fazer apenas o que ele se propõe a fazer.
A ostra ostreia, o gato gateia, o vento venta
(Prof. Clóvis Barros Filho)
Nossas classes devem seguir esta linha de pensamento, se é uma classe de serialização, ela serializa, seja em banco de dados, arquivos, memória. Não importa, ela apenas serializa.
Se nossa classe é de validação, ela apenas valida.
![]() |
Certo ou Errado?
Nos exemplos abaixo eu sempre colocarei o certo e o errado para compararmos as classes e as soluções propostas. Tentarei usar problemas e soluções do dia-a-dia. |
Antes de começarmos vamos ver a imagem abaixo:
Como podemos ver, é muito mais simples criar da forma errada. Mas te trará problemas de manutenção de código, de reusabilidade de código, seu código será macarrônico e anêmico. Alto Acoplamento e baixa coesão. No momento da manutenção deste código, erros simples se tornam complexos de serem resolvidos.
Como ferir o princípio.
Veja o exemplo de código abaixo:
A classe cliente escrita acima, tem diversos pontos que ferem o princípio da Responsabilidade Única:
- Ela é uma classe que se faz sua própria serialização, como pode ver na linha 17 do método “Adicionar()”, linha 23 do método “Atualizar()” e assim nos demais métodos. Logo esta classe tem que conhecer a implementação de sua forma de serialização, seja banco de dados, XML, JSON, memória;
- Esta classe é responsável por enviar um e-mail ao cliente, assim que o mesmo é cadastrado na aplicação. Imagina se você criar outras classes de pessoas, como Fornecedor, Usuário, Fabricante, e se fizer necessário o envio de e-mail ao se criar cada pessoa. Cada classe terá sua implementação do método “EnviarEmail()” e você terá que dar manutenção em cada método das classes de pessoas, se por um acaso o servidor for modificado, por exemplo;
- Esta classe é responsável por validar seus próprios dados. Em uma customização para clientes, esta abordagem seria trabalhosa, uma vez que cada cliente pode ter sua forma de validação de dados;
Como resolver o problema.
Como podem ver:
- Esta classe não se “Valida”;
- Para resolver este problema utilizamos o padrão de projeto “Strategy“. Que são:
- StrategyDependencyManager: Responsável por fazer a injeção de dependência das estratégias na classe cliente;
- IStrategy: Define o contrato para qualquer estratégia que não seja de persistência;
- IPersistenceStrategy: Define o contrato para as estratégias de persistência dos dados;
- StrategyBase: Abstração de estratégias para os tipos mais básicos;
- PersistenceStrategyBase: Abstração para estratégias de persistências;
- ClienteStrategy: Estratégia concreta para validação de clientes;
- A validação do CNPJ passou a ser de responsabilidade do padrão Validator (Visitor Pattern).
- IValidator: Contrato para classes de validação de tipos;
- CNPJValidator: Classe concreta para validação do tipo CNPJ;
- Estes tópicos, Visitor Pattern e Validators serão discutidos em outros artigos. Aqui iremos falar apenas do conceito S.O.L.I.D.
- Para resolver este problema utilizamos o padrão de projeto “Strategy“. Que são:
- Ela não conhece a implementação de serialização, no caso, podemos perceber que seria em um banco de dados;
- Este problema foi resolvido usando a classe DummyDBContext, mas temos que tomar cuidado com esta abordagem, pois depende do framework de acesso à dados que você vai utilizar, o mais comum, para desenvolvimento .NET é o Entity Framework. Este link do StackOverflow; em Português; tem uma boa explicação sobre com prós e contras;
- Ela não manda e-mails;
- Quem decide se o e-mail deve ou não ser enviado é a estratégia de cada cliente, para isso a estratégia utiliza-se do serviço de e-mail para o envio do e-mail para o cliente.
- EmailService: Classe de serviço de e-mail responsável por enviar e-mail e receber e-mail em toda a aplicação;
- Quem decide se o e-mail deve ou não ser enviado é a estratégia de cada cliente, para isso a estratégia utiliza-se do serviço de e-mail para o envio do e-mail para o cliente.
Como podemos ver, esta classe apenas faz o que lhe diz respeito. Manter os dados dos clientes.
![]() |
Não se preocupe com os nomes de classes e conceitos explicados acima como solução para a forma correta. Durante o desenvolvimento dos demais artigos, irei explicar todas as classes e os princípios aplicados.
Se não estiver aguentando a curiosidade. As classes e definições são melhores explicadas no Princípio de Inversão de Dependência (DIP). |
O fonte utilizado aqui pode ser baixado pelo GITHub em https://github.com/desenvolvedores-net/ArtigoSOLID
É isso ai pessoal 🙂
Até o próximo
♦ Marcelo