Adote os princípios SOLID: Boas práticas de programação
É extremamente importante implementar softwares adotando boas práticas de programação, sobretudo com princípios SOLID. Elas propiciam o desenvolvimento de um código limpo, legível e testável. Diante dessa perspectiva, os sistemas atualmente implementados pela dti digital crafters são embasados nos princípios SOLID proposto por Robert C. Martin, por volta do ano 2000.
Propomos neste material abordar algumas violações x código adequado de acordo com os princípios instituídos pelo SOLID.
Sumário
- 1 Princípio SSRP – Single responsibility principle
- 2 Precisamos falar sobre SGBD quando falamos de princípios SOLID
- 3 Princípio OOCP – Open/Close principle
- 4 Princípio LLSP – Liskov substitution principle
- 5 Princípio IISP – Interface segragation principle
- 6 Princípios de substituição
- 7 Princípios SOLID em DDIP – Dependency Invension Principle
- 8 Segregação de Interface
- 9 Referências – Princípios SOLID
Princípio SSRP – Single responsibility principle
Observe a seguinte classe:
Acredita que o método dicionarUmaNovaPessoa() deveria ser responsável por realizar tantas coisas? Como definir o modelo dos dados persistentes da aplicação, instanciar conexão e realizar manipulação de dados no banco? A solução para esse problema pode ser apontado a seguir:
Note que a organização dos arquivos foi alterada, agora as classes estão divididas de acordo com as suas responsabilidades.
As classes CPFServices.cs e EmailServices.cs são responsáveis por validar os dados de CPF e E-mail da pessoa que se pretende cadastrar.
O método EValida() destas classes garante a validação dos dados, perceba que estes métodos são chamados na classe Pessoa.cs que contém os dados persistentes da aplicação (como um espelho da estrutura do banco de dados).
Precisamos falar sobre SGBD quando falamos de princípios SOLID
A classe PessoasRepository.cs responsabiliza-se pelo gerenciamento dos dados, logo a instanciação de conexão e definição dos métodos de adição de dados no Sistema Gerenciador de Banco de Dados (SGBD) devem ser definidos nesta classe. (Obs.: Isso ainda irá ser melhorado, não levem como verdade absoluta)
Por fim, a classe PessoaService.cs valida os dados e realiza o cadastro da Pessoa, com base nos métodos e classes que agora estão separados de acordo com sua responsabilidade.
Princípio OOCP – Open/Close principle
Neste exemplo, criou-se uma classe enum para armazenar os turnos.
Uma classe RemuneraçãoPorTurnos também foi criada para implementar o salário que algum funcionário recebe por cada turno, dessa forma bastaria alterar esta classe de acordo que surgissem novas demandas de turnos e acrescentar um if com a lógica correspondente à mudança.
Porém, alterar uma classe já em funcionamento não é legal. Pensando nisso, podemos adicionar uma classe RemuneracaoBase que possa ser implementada por cada turno com sua lógica correspondente. Tal classe pode ser extensível para suas classes derivadas e fechada apenas naquele escopo que pretende atender. Veja o exemplo:
Quero agora a remuneração para o turno matutino, assim:
Princípio LLSP – Liskov substitution principle
Princípio de substitução de Liskov , pode ser apresentado pela seguinte diagramação UML:
Salienta-se que a classe Quadrado é similar à classe Retangulo, porém com uma característica especial: a largura e a altura são iguais. Logo, à primeira vista tudo parece correto (principalmente de forma conceitual, pois um quadro é um caso especial de um retângulo). Na notação UML classe Quadrado se apresenta com uma classe derivada e a classe retângulo configura-se como a classe base
Note que na classe Retangulo, definiu-se a altura, largura e uma função para cálculo de área. E diante do nosso contexto, a classe Quadrado deve herdar de retângulo e sobreescrever seus métodos.
Porém , como a classe quadrado herda de retângulo, esta também herdará a altura e largura da classe base. Isso não faz sentido, pois a altura e largura do retângulo não são iguais, o que descaracteriza as propriedades de um quadrado.
A solução é simples:
Ao definir a classe paralelogramo, é possível atribuir os dados de altura e largura corretos para cada uma das figuras geométricas, com isso o cálculo da área será feito corretamente.
Princípio IISP – Interface segragation principle
Um claro exemplo da utilização de interfaces generalistas demais pode ser apresentado a seguir:
Perceba que a interface ICadastroGeral possui métodos para validar as informações, salvá-las no banco de dados e enviar e-mail confirmando o cadastro. Mas esses métodos são aplicáveis a todas as classes que implementam a interface?
Perceba que para a classe de CadastroMercadoria a interface não seria aplicável, pois uma mercadoria não possui um e-mail. Pense em criar interfaces específicas, não importa quantas interfaces tem sua solução desde que sejam aplicáveis a todos os casos!
Princípios de substituição
Este tópico trata, sobretudo, do princípio da substituição Liskov: Um conceito importante para quem deseja se aprofundar mais nos princípios de S.O.L.I.D, como os já apresentados anteriormente. Embora seja mais subjetivo, o princípio em questão diz que em um aplicativo, o objeto determinado pode ser facilmente substituído por outro objeto de um tipo derivado: Isso tudo sem sofrer qualquer impacto. Estamos falando claramente sobre conceitos abstratos e definição de contratos por meio de interfaces. Para melhor demonstrar esse princípio, imaginemos um programa bancário que exibe um relatório completo sobre as taxas de juros do cliente. No relatório, temos o arquivo do cliente e informações sobre as taxas.
Princípios SOLID em DDIP – Dependency Invension Principle
O princípio de inversão de dependências diz respeito à depender de uma abstração e não de uma implementação. Nesse caso, todos os demais princípios são aplicados, garantindo que os sistemas sejam o mais desacoplados e coesos possível. Para isso, recomenda-se trabalhar com a injeção de dependências. Em linhas gerais, “Injetar” uma dependência, nada mais é que passar uma classe (habitualmente uma classe interface) que será utilizada, para outra que irá consumir seus recursos.
Diante do que foi apresentado até aqui, a proposta do DDIP é prover um conjunto de interfaces específicas, classes que trabalhem com responsabilidade única e que sejam fechadas no seu escopo e abertas para extensão.
A classe PessoaServices.cs é neste caso, responsável por controlar as manipulações e verificações de dados da pessoa que for cadastrada no sistema. Neste caso, o construtor desta classe, está assim definido:
Segregação de Interface
Uma forma de otimizar o trabalho de toda e qualquer pessoa que trabalha com desenvolvimento é a quebra de alguns paradigmas pré-estabelecidos na área. O princípio de segregação parte do ponto de condução para que os desenvolvedores não tentem reaproveitar suas interfaces, porque há uma citação que diz: “muitas interfaces específicas são melhores do que uma interface única.”
Existem formas de encontrar solução para a segregação de interface. Com uma aplicação otimizada, ele nos da a possibilidade de utilizar o próximo princípio da inversão de dependência, inversão de controle e que nos leva a injeção de dependência.
Perceba que para adicionar uma nova pessoa neste exemplo, será preciso injetar duas classes para validação e adição de dados. Dessa forma, para que seja possível construir uma classe PessoaServices é preciso passar a referência das interfaces IEmailServices e IPessoaRepository. Lembramos também que esse é um princípio indispensável para quem busca se aperfeiçoar em princípios SOLID.
Note que o método AdicionarPessoa(Pessoa pessoa), é responsável apenas por adicionar uma nova pessoa, delegando à _pessoaRepository adicionar os dados dessa pessoa em um repositório de informações (pode ser um banco de dados, em memória, dentre outros) e à _emailServices enviar um e-mail comunicando que a pessoa foi cadastrada com sucesso !
Esperamos que este artigo seja útil a todos para entendimento e adoção do SOLID em suas aplicações. Obrigado !
Referências – Princípios SOLID
- https://www.devmedia.com.br/padrao-de-injecao-de-dependencia/18506
- https://medium.com/thiago-aragao/solid-princ%C3%ADpios-da-programa%C3%A7%C3%A3o-orientada-a-objetos-ba7e31d8fb25
- https://www.eduardopires.net.br/2013/04/orientacao-a-objeto-solid/
Tem interesse em integrar um time que entende de agilismo e tecnologia na prática? Confira todas as vagas disponíveis em nossa página de carreira e se cadastre na que mais combina com o seu perfil. Não perca tempo e venha ser dti!
Produtos Digitais
Confira outros artigos
Produtos digitais: entregas contínuas com IA
Nas últimas semanas, lançamos uma série de artigos sobre o uso de inteligência artificial no processo de construção de produtos digitais. Neles, apresentamos alguns aceleradores que a dti tem utilizado para potencializar a eficiência dos times. Abordamos a fase de concepção do produto, as atividades de gestão e design, o desenvolvimento do software e a […]
Produtos Digitais
Inteligência Artificial: acelerando o design e gestão de produtos digitais
Como aproveitar o melhor da Inteligência Artificial Generativa para gerar mais valor? Essa tem sido uma pergunta recorrente no mercado conforme as empresas buscam entender e adotar a tecnologia. Embora existam muitas dúvidas e hipóteses não comprovadas, parece ser consenso que os avanços na Inteligência Artificial impactarão significativamente muitas profissões. No relatório The economic potencial […]
Produtos Digitais
IA Generativa: acelerando a concepção de produtos digitais
Como as empresas podem responder às crescentes demandas por produtividade e eficiência em um mundo digital em constante mudança? O período pandêmico acelerou a digitalização de várias empresas e agora o desafio é outro. Entramos em uma era de incertezas, na qual não há mais espaço para desperdícios ou prolongados ciclos de entrega de software. […]
Produtos Digitais