Uma das maiores dificuldades no desenvolvimento de software é olhar para o código desenvolvido e dizer “Essa solução foi uma das melhores, meu código está muito bom”. Qual o motivo que faz com que as pessoas desenvolvedoras tenham essa sensação?
Não conseguimos responder essa questão com facilidade, mas esse assunto é diretamente ligado aos princípios do SOLID que podem ajudar a enxergar melhor o desenvolvimento e aprimorar a codificação.
O que é SOLID?
SOLID é um acrônimo dos cinco primeiros princípios da programação orientada a objetos e sua divisão consiste em:
- [S]ingle Responsability Principle (Princípio da Responsabilidade Única);
- [O]pen/Closed Principle (Princípio do Aberto/Fechado);
- [L]iskov Substitution Principle (Princípio da Substituição de Liskov);
- [I]nterface Segregation Principle (Princípio da Segregação de Interfaces);
- [D]ependency Inversion Principle (Princípio da Inversão de Dependências).
O objetivo deste artigo é mostrar como esses princípios podem ser aplicados no dia a dia no desenvolvimento de software. Vamos lá!
O dia a dia de pessoas desenvolvedoras
O principal objetivo do desenvolvimento de sistemas é a entrega de valor, mas esses valores são vistos de diferentes perspectivas, e aqui vamos abordar a perspectiva do time de desenvolvimento.
Para o time de desenvolvimento, entregar valor consiste em ter um código bem escrito e o produto funcionando como o cliente contratou. Porém, é difícil determinar o que significa ter esse código bem escrito, então para isso existem técnicas e padrões de projeto para auxiliar no desenvolvimento de sistemas, e o SOLID encaixa perfeitamente para a escrita de um código mais limpo: o seu entendimento é bem simples e a aplicabilidade é bem fácil.
Aplicando os cinco princípios com uma linguagem simples
Imagine que neste momento estamos desenvolvendo uma funcionalidade nova como, por exemplo, um fluxo de pagamento, e esse fluxo possui dois tipos de pagamento: boleto e cartão de crédito. No início do desenvolvimento criamos uma única classe, e percebemos que no decorrer, as regras de boletos são diferentes das do cartão de crédito e que estão todas na mesma classe. Aqui aplica-se o SRP (Single Responsability Principle), onde separamos as regras de boleto das de cartão de crédito, cada uma em sua respectiva classe, e possuímos um contrato, uma interface chamada, por exemplo, PaymentMethod. Nesse exemplo parece simples, mas sabemos que um fluxo de pagamento é muito mais complexo e que o difícil é definir o que é responsabilidade.
Agora, e se nosso fluxo de pagamento possuir descontos para quem paga a fatura antes do prazo: até 10 dias antes 10% de desconto, após 10 dias e até 5 dias antes 5% de desconto para compra via boletos e para cartão de crédito – para pagamento à vista – temos 15% de desconto, para pagamento em até três vezes 10% de desconto e assim o sistema vai ficando cheio de regras, vai se tornando complexo e começam alguns questionamentos por parte do desenvolvimento, como por exemplo:
“Qual a melhor maneira de desenvolvimento para futuras manutenções?”
Se analisarmos o caso anterior podemos visualizar uma grande quantidade de ifs para solucionar o problema e com isso vamos acoplando cada vez mais o código, então aqui temos o princípio OCP (Open/Closed Principle): aberto para extensão e fechado para alteração.
Neste momento utilizaremos abstração para tornar nosso código mais robusto. No caso do nosso exemplo poderíamos criar uma abstração PaymentMethod que será um contrato para os meios de pagamentos serem implementados. Esse contrato já faz parte do princípio LSP (Liskov Substitution Principle) que significa garantir que as classes derivadas sejam usadas transparentemente onde se vê uma classe base. Ao utilizar abstração é muito comum que as interfaces fiquem com mais responsabilidades do que deveriam, então, aqui podemos aplicar o princípio ISP (Interface Segregation Principle), que nos diz que é sempre melhor termos interfaces magras com responsabilidade única.
O desenvolvimento da funcionalidade anterior nos leva a abstração e ao último princípio: DIP (Dependency Inversion Principle).
Antes de falarmos do último princípio uma pergunta: É possível eliminar o acoplamento? Não é possível, como sabemos em sistemas de médio e grande porte uma classe sempre dependerá de outra, portanto, o importante é diferenciar o acoplamento, por isso esse princípio nos mostra que um classe deve depender sempre de um módulo mais estável que ela. No nosso exemplo PaymentMethod deve ser mais estável, com poucas mudanças, pois outras classes dependerão dela.
O artigo é para demonstrar de uma maneira simples a importância de princípios para o desenvolvimento de software. Claro que no dia a dia o trabalho que desenvolvemos é mais complexo, porém, devemos começar a pensar mais abstratamente e ir aplicando o que aprendemos em vários módulos, não de uma única vez, mas aos poucos. Assim, será possível notar a evolução na escrita do código.
Quer ajustar ou complementar o conteúdo? Deixe seu comentário abaixo
1 Comentários
Sendo um tanto chato, acho que um júnior ou mesmo pleno que nunca ouviu falar de SOLID, não vai compreender muita coisa desse artigo. Poderia ser mais didático e ter trechos de código mostrando violação e adequação de cada princípio.