Uma abordagem teórica e prática de SOLID, através de Padrões de Projeto e Clean Code. — Parte 1

Marcelo Soares
CWI Software
Published in
8 min readJul 8, 2020

“Esse texto tem o intuito de discutir, apresentar e aplicar SOLID, PP e CC, mas com uma pitada de teoria, história, experiência do dia-a-dia, sarcasmo e um pouco de crítica. Não sou o dono da verdade, então, caso alguém se sinta ‘ofendido’, já receba minhas singelas e verdadeiras desculpas.”

Introdução

vem de anos, que os termos SOLID, Padrões de Projeto e Clean Code, vem sendo falados, debatidos, escritos em livros e sites. Encontramos essas palavras até em vagas de emprego, como pré-requisitos, para obtenção das pretendidas oportunidades. Mas será mesmo que, depois de todo esse tempo e material relacionado ao conteúdo comentando, os profissionais da tecnologia conhecem e sabem aplicá-los no seu dia-a-dia ? Para responder essa pergunta, precisamos explorar e conhecer os tipos de profissionais que existem na área de desenvolvimento de software e, a partir disso, tentar construir, ou não, uma resposta. Mas já posso adiantar que uma parte destes desconhecem, ou não aplicam, os princípios SOLID, padrões de projeto e clean code, como será apresentado nesse texto.

Começando, na primeira classe trabalhadora do campo da tecnologia, encontra-se as pessoas de início de carreira, que estão cursando a faculdade, estagiando e iniciando em seu primeiro emprego. Depois, vem os que já são formados ou não, mas que possuem uma experiência no campo da programação. E por fim, os veteranos, homens ou mulheres, considerados “sênior”, dentro da área. Vejamos, para a primeira leva de programadores, definidos como os estudantes/estagiários; não conhecer SOLID, nós podemos entender, visto que estão iniciando em sua carreira, onde na universidade, desfrutarão ao acesso desse conhecimento. A segunda, os profissionais de grande bagagem na área. Esses, eu faço uma divisão, ou melhor, uma subdivisão desse tipo. Vou fracionar em três partes, vejamos:

  • Os que não sabem (N)
  • Os que sabem, mas não aplicam (SN)
  • Os que sabem e aplicam (SA)

A fim de não repetir muito as palavras, coloquei no lado um codinome para cada subdivisão. Os que não sabem (N), realmente, desconhecem de tais técnicas, pois não tiveram contato na faculdade, e aqui vai uma parênteses. Na minha graduação em meados dos anos 2004 à 2011, não obtive nenhuma cadeira referentes a SOLID, PP e CC. E acredito que algumas instituições de ensino superior continuam não apresentando tais disciplinas, e, fazendo uma pequena propaganda “Alô, Taciano!!!”, a que leciono atualmente, há um semestre inteiro, descrevendo tais métodos e ou procedimentos; fecho parênteses. Dessa forma, esses profissionais, além de não terem estudado na faculdade, passaram a não procurar conhecer, estudar e aprender as técnicas. Os (SN), são os desenvolvedores que apelidei carinhosamente, de “mas é só” ou “mas porque”. Isso vem do fato, que toda frase dita por esse tipo, sempre tem um…

  • Mas é só copiar e colar lá na outra classe ?”
  • Mas por que criar testes unitários ?”
  • Mas é só uma pequena alteração !”
  • Mas é só deixar aqui, que vai funcionar !”
  • Mas por que criar essa interface?”
  • Mas por que remover as linhas comentadas, já que posso usar futuramente esse código novamente !”

Essas perguntas também valem para os “Os que não sabem (N)”, mas a diferença aqui é que os (N) questionam por não saber de clean code por exemplo, já os (SN), questionam, ao meu ver, pelo fato de não entenderem a importância de aplicar as técnicas de SOLID, PP e CC, mesmo tendo o conhecimento no assunto. Exemplo, o desenvolvedor sabe fazer um teste unitário com Junit, mas não sabe da sua relevância, que isso traz ao projeto, pois se algum dia, alguém porventura, mudar o código, o seu teste vai “pegar”. Ou se, aquele código copiado de uma classe para outra, necessitar ser alterada, todas as demais que estão duplicadas, devem ser ajustadas. E por últimos, os (SA), no qual esses sabem do valor das boas práticas de programação. É um grupo que compreende a dimensão e relevância de algumas das boas técnicas abaixo:

  • que não se deve retornar um “null” em um método, mas sim um “null object”.
  • o que é lei de Demeter
  • que se programa para interfaces e não implementação. O valor das interfaces, ou seja, o poder da abstração.
  • que cada classe tem uma única responsabilidade
  • a relevância dos testes

Essas foram algumas boas práticas de tantas outras, que um programador (SA), conhece e aplica. Por fim, temos os “veteranos”, os velhos de guerra, lá da época do Cobol, Clipper e C. Alguns desses desenvolvedores, com o passar do tempo, acabam não se atualizando, não buscando novos conhecimentos, em que a partir disso, terminam parando no tempo. Em contrapartida, temos os “veteranos” que, mesmo através dos anos, continuam com aquela fome de adolescente, para as novas tecnologias e conhecimentos.

Tentando trilhar um caminho, para buscar uma resposta mais precisa para a pergunta inicial, e, considerando os tipos de profissionais aqui relatados, somado a tudo que já observei durante os 16 anos de experiência na área de desenvolvimento e educação, posso responder, de forma muito humilde e sucinta, que uma grande parte dos profissionais não conhece e nem sabe aplicá-los realmente no seu dia-a-dia, os princípios SOLID, padrões de projeto e clean code.

Baseado em todo esse cenário exposto, e acrescido por uma vontade de escrever sobre um assunto que tenho tanto interesse; venho através deste artigo, que será divido em algumas partes, apresentar, explicar, comentar e descrever de forma muito prática e teórica, através de cases reais, o SOLID, PP e CC. Da mesma forma, as suas importâncias dentro do contexto do desenvolvimento de software e como essas técnicas podem transformar seu jeito de construir uma aplicação, e, consecutivamente, transformando você num profissional diferenciado no mercado.

Apresentando os princípios SOLID, Padrões de Projeto e Clean Code

Antes de começar a parte prática, é importante conhecer um pouco de história dessas siglas; suas origens, a teoria atrás delas, as pessoas responsáveis pelos seus desenvolvimentos, quando e porque usar. Acredito da importância desse embasamento histórico e teórico, a fim de o desenvolvedor perceber o que está por trás de tudo isso, quando estiver aplicando-as.

Começando pelo S.O.L.I.D, que é o acrônimo de cinco princípios que segundo Martin. Robert C. (2011,p. 122)

descrevem os princípios de projetos orientados a objetos que ajudam os desenvolvedores a eliminar os sintomas do projeto ruim — os maus cheiros de projeto — e a criar os melhores projetos para o conjunto de funcionalidades atuais. Esses princípios resultam de décadas de experiência em engenharia de software. Eles não foram produzidos por uma só pessoa, mas representam a integração das ideias e publicações de uma grande quantidade de desenvolvedores de software e pesquisadores.

Como descrito por Robert Martin, também conhecido como “tio Bob”, os princípios SOLID servem como uma forma de evitar ou eliminar problemas em sistemas, como ele mesmo escreveu “ruim”. Alguns sintomas de projetos ruins são: “Rigidez: é difícil alterar o projeto, Fragilidade: o projeto (design) é fácil de estragar, Imobilidade: é difícil reutilizar o projeto, Viscosidade: é difícil fazer a coisa certa, Repetição: desnecessário., ” (MARTIN ROBERT C., 2011, p. 122). Abaixo são apresentados os princípios:

  • O Princípio da Responsabilidade Única (SRP)
  • O Princípio do Aberto/Fechado (OCP)
  • O Princípio da Substituição de Liskov (LSP)
  • O Princípio da Segregação de Interface (ISP)
  • O Princípio da Inversão de Dependência (DIP)

Começando a detalhar os princípios, podemos iniciar pelo (SRP — Single Responsibility Principle), que “foi descrito no trabalho de Tom DeMarco e Meilir Page-Jone. Eles o chamavam de coesão, o que definiam como a afinidade funcional dos elementos de um módulo” (MARTIN ROBERT C., 2011, p. 135). Esse é o princípio mais simples de entender, onde devemos respeitar a seguinte premissa, “Uma classe deve ter apenas um motivo para mudar”. Ou seja, uma classe deve fazer uma única tarefa e mais nada. Quando se tem grandes classes , ou aquelas que “fazem tudo”, com certeza, estas, estão violando o (SRP). Mas o que seria fazer uma única tarefa ? Vejamos um exemplo simples, onde uma classe de serviço da camada de negócio, recebe uma entidade para salvar em uma base dados. Ao fazer isso, o método na qual vai realizar o processamento, executa, dentro da própria classe, as validações de negócio e após persiste os dados. O ponto da validação viola o princípio, visto que a classe de negócio, a sua única responsabilidade é ser um “intermediador” entre vários locais do sistema. Dessa forma, devemos ter uma class que realizar somente as validações, na qual, ela será invocada pela nossa service e, posteriormente, gravar os dados. Nesse momento, alguns podem começar a questionar, mas por que não deixar as validações na classe de negócio?”. Poderia responder com diversos argumentos, mas seguem alguns; a fácil criação de testes unitários, o reaproveitamento do código da validação em qualquer ponto do sistema e, por fim, a dimensão de nossas classes, que mantêm-se muito enxutas, visto que, estão tratando somente um contexto. Isso vai ao encontro de uma das técnicas do Clean Code, a de termos funções e classes pequenas.

O segundo princípio (OCP — Open/Closed Principle) é definido como: “As entidades de software (classes, módulos, funções e etc) devem ser abertas para ampliação, mas fechados para modificações”. Este é um dos mais controversos, pois ouço muitas pessoas comentando: “mas como fechar uma classe e deixar aberta para ampliações ?” Ou seja, como fazer novas features e correções no programa sendo uma classe “fechada para tal”. Para responder a esta contradição, é importante entender que não existe a “mágica” para isso, visto que em certas situações, as transformações são inevitáveis. “Não existe um modelo que seja natural para todos os os contextos” (MARTIN ROBERT C., 2011, p. 148). O que (OCP) propõe, é evitar as alterações no código fonte e, quando fazê-las, utilizar as abstrações, pois o grande entendimento desse princípio é que mudanças tendem a gerar bugs, e se nós minimizamos ao máximo, evitamos injetar erros no sistema.

As abstrações são realizadas a partir de conceitos da programação orientado a objeto, como interfaces, heranças e composições, estendendo-se aos padrões de projetos. Dentro do campo dos PP, podemos citar Strategy, Composite e Observer como exemplos. Um caso muito visto em tutoriais para apresentar esse princípio, é o cálculo do salário de um funcionário, onde é criado uma interface, e a partir dessa, é gerada implementações para cada funcionário e no fim, uma classe de contexto para executar a lógica, sendo usada strategy como pattern.

Os frameworks e servidores de aplicações fazem uso direto de (OCP), através da técnica de “ganchos” ou do inglês (hook), que consistem em executar uma ou mais rotinas do usuário, onde estas estão contidas nas classes dos frameworks e application server. As ferramentas citadas, ao perceberem que existem códigos a serem executadas, as invoca ou puxa “como um ganho” e as executa. As rotinas geralmente são inseridas por meios de injeção de dependência, instanciação de objetos definidos em arquivos ou injetados diretamente na classe, através de um método.

Podemos citar o exemplo de acesso a uma API Rest, usando qualquer container web, na qual a implementação da API é o código do usuário a ser executado. Por meio das formas de inserções que foram comentadas, o framework deve “puxar” a implementação de uma abstração (interface) a ser executada, em certos momentos de sua execução.

No código abaixo, desenvolvi algo muito simples, para visualizar o (OCP), em cima da técnica de hook, usando composição.

public class ExecuteAPI {
private API api;

public void execute() {
// algum código do framework
if(api != null) {
// (OCP), nao houve alteração,
//mas o código está aberta para ampliação.
api.processMethod(); // gancho (hook)
}
// algum código do framework
}

public void addApi(API api ) {
this.api =api;
}
}

Como é possível ver no fluxo, a classe que executa a API não foi alterada, mas mesmo assim ela conseguiu executar um procedimento, ou seja, a classe está “aberta para ampliação”.

Para concluir o (OCP), é importante reforçar que o princípio não deve ser aplicado de forma compulsiva, desenvolvendo abstrações desnecessárias em nossa aplicação “… não é recomendado aplicar abstração desenfreada em todas as partes do aplicativo…”(MARTIN ROBERT C., 2011, p. 152).

Finalizo então essa primeira parte do artigo. Na próxima, vamos abordar os demais princípios, com exemplos práticos e teóricos.

Referências

Martin, Robert C.; Martin, Micah (2011) “Príncipios, Padrões e Práticas Ágeis em C#”

Martin, Robert C. (2011) “Clean code: a handbook of agile software craftsmanship.”

Aniche, Maurício (2013) “Orientação a objetos e SOLID para ninjas, Projetando classes flexiveis”

Marcelo Soares

mbsoares.infor@gmail.com

--

--

Marcelo Soares
CWI Software

Desenvolvedor e professor da área de Tecnologia da informação.