SOLID: o que é e como utilizá-los nos seus projetos
São cinco princípios da programação orientada a objetos que facilitam no desenvolvimento de softwares, tornando-os fáceis de manter e estender.
O que é SOLID?
SOLID é um acrônimo criado por Michael Feathers, após observar que cinco princípios da orientação a objetos e design de código - criados por Robert C. Martin (a.k.a. Uncle Bob) e abordados no artigo The Principles of OOD - poderiam se encaixar nesta palavra.
S.O.L.I.D: os 5 princípios da POO
S - Single Responsibility Principle (Princípio da Responsabilidade Única)
O - Open-Closed Principle (Princípio Aberto-Fechado)
L - Liskov Substitution Principle (Princípio da Substituição de Liskov)
I - Interface Segregation Principle (Princípio da Segregação da Interface)
D - Dependency Inversion Principle (Princípio da Inversão da Dependência)
Esses princípios ajudam o programador a escrever códigos mais limpos, separando responsabilidades, diminuindo acoplamentos, facilitando na refatoração e estimulando o reaproveitamento do código.
1. SRP - Single Responsibility Principle
Esse princípio declara que uma classe deve ser especializada em um único assunto e possuir apenas uma responsabilidade dentro do software, ou seja, a classe deve ter uma única tarefa ou ação para executar.
Exemplo prático do SRP:
A classe Order viola o SRP porque realiza 3 tipos distintos de tarefas. Além de lidar com as informações do pedido, ela também é responsável pela exibição e manipulação dos dados. Lembre-se, o princípio da responsabilidade única preza que uma classe deve ter um, e somente um, motivo para mudar.
A violação do SRP pode gerar alguns problemas, sendo eles:
Falta de coesão - uma classe não deve assumir responsabilidades que não são suas;
Alto acoplamento - Mais responsabilidades geram um maior nível de dependências, deixando o sistema engessado e frágil para alterações;
Dificuldades na implementação de testes automatizados - É difícil de “mockar” esse tipo de classe;
Dificuldades para reaproveitar o código;
O código acima está sendo responsável por mais de uma ação, pois além de representar uma venda está fazendo a lógica de uma formatação para ser escrita em um arquivo, não que o código esteja errado mas onde se encontra não seria o melhor lugar para estar, pois é um risco, visto que, quando for realizar algum ajuste nesta classe pode acontecer algum imprevisto, como alterar algo sem necessidade na formatação.
Como proposta do tópico, é recomendado realizar a separação do código, criar uma classe que cuide dessa responsabilidade e de outras futuras caso outras formatação sejam feitas. Isolando esse trecho de código a pessoa designada a realizar a manutenção não tem a necessidade de se preocupar com a parte de vendas, e sim somente com a formatação.
O princípio da responsabilidade única não se limita somente a classes, ele também pode - e deve - ser aplicado em métodos e funções, ou seja, tudo que é responsável por executar uma ação.
2. OCP - Open-Closed Principle (Princípio Aberto-Fechado)
Objetos ou entidades devem estar abertos para extensão, mas fechados para modificação, ou seja, quando novos comportamentos e recursos precisam ser adicionados no software, devemos estender e não alterar o código fonte original.
Exemplo prático do OCP:
1 - Ler login e senha do cartão NFC
2 - Fazer login com cartão
1 - Gravar token do evento para download
2 - Ler login e senha do cartão NFC
3 - Fazer login e download do evento
4 - Fluxo
4.1 - somente login
4.2 - somente login e hash do evento
1 - Uso a classe leitura de login e senha
2 - Uso a classe leitura de Hash
_
1 - Vou ter duas variáveis na mesma tela
2 - Controlar estado de duas variáveis
3 - Se for login tem que ser uma se for download tem que ser outra
Quando desenvolvemos algo que contempla algum comportamento ou regra do sistema, e quando surge algo novo para ser implementado ou uma nova regra o ideal é não mexer na parte que está funcionando e sim fazer uma extensão do que está pronto para a nova implementação.
O código acima possui dois fluxos de execução que levam a retornos diferentes, o retorno de cada fluxo é feito através de uma nova instância que implementa uma INTERFACE para distinguir as regras de comportamento na leitura de NFC, this.cardReader é do tipo da interface ReaderCardLogin.
Ambas implementam CardReaderLoginListerner mas somente uma implementa SetupEventListener que é responsável por ler o hash, sendo assim o código é separado por suas responsabilidades, o que facilitará a manutenção.
3. LSP - Liskov Substitution Principle (Princípio da substituição de Liskov)
Esse princípio declara que uma classe derivada deve ser substituível por sua classe base.
Esse princípio tem como objetivo trocar a instância de uma classe passada por parâmetro e o comportamento funcionará de forma transparente, o intuito é ter uma classe base com os comportamentos esperados e a partir dessa classe criar as outras e cada classe ser responsável pelas operações executadas.
No exemplo acima, a classe Payment que será estendida pela classe do método de pagamento, como: boleto, pix, cartão de crédito e débito. Cada instância de método de pagamento poderá ser utilizada no método checkout(Payment payment, long price).
4. ISP - Interface Segregation Principle (Princípio da Segregação da Interface)
Uma classe não deve ser forçada a implementar interfaces e métodos que não irão utilizar.
Esse princípio basicamente diz que é melhor criar interfaces mais específicas ao invés de termos uma única interface genérica.
No exemplo acima temos a implementação de uma interface um tanto quanto genérica que foi desenvolvida para atender uma funcionalidade, entretanto, acabou sendo usado em outra parte do sistema, no qual alguns do seus métodos iriam ser utilizados, dessa forma, ficou alguns métodos sem comportamento na execução, somente com a escrita de logs.
A maneira correta de fazer seria criar outra interface com os métodos que ambas iriam utilizar e fazer com que a interface atual herdasse a outra mais genérica, assim cada parte do sistema teria que implementar somente o necessário e não ficaria os métodos “vazios” só por estar.
5. DIP - Dependency Inversion Principle (Princípio da Inversão de Dependência)
De acordo com Uncle Bob:
1. Módulos de alto nível não devem depender de módulos de baixo nível. Ambos devem depender da abstração.
2. As abstrações não devem depender de detalhes. Detalhes devem depender de abstrações.
Vamos entender tudo isso na prática através de exemplos:
Interface com as ações:
Classe intermediária:
Na questão de abstração temos duas possibilidades de trabalhar: com classes abstratas, na qual podemos definir um comportamento padrão e com interfaces na qual cada implementação e detalhes serão tratados em cada situação.
No exemplo proposto temos uma interface para adicionar e remover item da lista de compra, em um segundo momento temos uma listagem de produtos onde a interface é recebida na criação da tela e através dessa interface o item será adicionado na lista de compra, então a listagem de produto nem faz ideia de como isso deve acontecer, sendo isso abstraído pela interface, se os itens serão salvo em arquivo, no banco de dados ou em cache não cabe a listagem de produtos saber dessas informações. Com essa ideia, amanhã ou depois, por uma questão de definição, o comportamento de salvar os itens será alterado, nenhuma alteração será necessária na parte de listagem de produtos.
Conclusão
A sistemática dos princípios SOLID tornam o software mais robusto, escalável e flexível, deixando-o tolerante a mudanças, facilitando a implementação de novos requisitos para a evolução e manutenção do sistema.
Pode ser um pouco assustador no início usar todos esses princípios, nem sempre conseguiremos aplicar todos em nosso projeto, mas com a prática e constância, aos poucos vamos adquirindo a experiência necessária para escrever códigos cada vez mais maduros, já que, os princípios SOLID servem como guias para isso.
Análise: procure uma solução inteligente
Reflita sobre o código: faz parte do dia a dia, não escreva código ruim, dói no coração.
Escreva menos: escreva melhor, pense que amanhã você irá mexer no código
Fontes: www.medium.com