top of page

Guia de Boas Práticas de Programação

Boas práticas de programação são padrões de desenvolvimento que quando seguidos, criam consistência na base de código, melhoram a legibilidade do código, reusabilidade e manutenibilidade. Alguns exemplos comuns são as orientações do “Uncle Bob” em Clean Code, e aqui iremos passar por algumas boas práticas em Apex e com isso, iremos também introduzir Padrões de Projeto (design patterns), que abordarei com mais ênfase em posts futuros (alguns sendo escritos paralelamente a esse).


Regra dos Escoteiros

Atribuem aos escoteiros a regra que diz algo nas linhas de “Deixe o acampamento mais limpo do que você o encontrou”. Quando aplicamos isso ao desenvolvimento de software, temos 4 pontos de atenção e atuação

  1. Refatoração Contínua: Sempre que você tocar em alguma parte do código, tente melhorar sua clareza, eliminar duplicações ou simplificar a lógica

  2. Pequenas Melhorias: Não é necessário fazer grandes refatorações de uma vez. Pequenas melhorias, com o tempo, criam uma grande melhoria.

  3. Código Legível: Tente deixar o código sempre fácil de entender. É melhor gastar mais alguns minutos escrevendo o código do que algumas horas tentando entender o mesmo no futuro.

  4. Eliminação de Débito Técnico: Sempre que possível elimine débitos técnicos, como código comentado, variáveis não utilizadas ou funções obsoletas

Pessoalmente, além dessas 4 regras, gosto de adicionar documentação sempre que possível, assim não só fica mais fácil que alguém lide com o código no futuro, como também auxilia a explicar o que o código faz para pessoas da equipe que não lidem com código.


Simplificação de Lógica

Muitas vezes encontramos códigos como:


E não há nada de errado com ele, porém temos alguns pontos de atenção:

  • Caso sejam adicionados mais status, a execução desse código será mais lenta.

  • Caso seja necessário adicionar ou remover algum status, será um pouco mais complexo, dado que a lista pode ser muito maior do que essa

  • A leitura, embora simples, é um pouco prejudicada, por ser algo como “Se status for igual a ‘Active’, ou se status for igual a ‘Pending’ ou se status for igual a ‘In Progress’” que não é nada fluida.

Podemos melhorar esse código então usando a seguinte sintaxe:


Agora, além de melhorarmos o tempo de execução do código, ainda melhoramos sua leitura, se tornando algo nas linhas de: “Se status for igual a: ’Active’, ‘Pending’ ou ‘In Progress’”.

Porém, ainda seria possível, uma terceira variação do código:


Nessa situação, criamos a mesma lista de status, mas movemos sua declaração e inicialização para o topo do código e a tratamos como uma constante. Nessa situação, podemos utilizar essa lista múltiplas vezes caso haja necessidade e lemos o código como “Se o status for válido”.

Simplificação de código sempre o deixa mais elegante. Embora custe algum tempo fazer isso, a manutenção a ser feita no futuro compensa esse tempo. Um código simples e limpo também é menos propenso a apresentar erros e bugs. No inicio pode ser difícil escrever um código simples, mas te garanto que com o tempo, isso se torna uma segunda natureza.

Eu sei que muitas vezes queremos mostrar o nosso domínio sobre a linguagem e o quanto nós sabemos o que nos leva a criar um código extremamente complexo, que poucas pessoas podem ler. Eu mesmo já fiz isso mais vezes do que gostaria de admitir, mas de algum tempo pra cá, sempre me lembro da seguinte imagem (essa versão é do site commadot)


Quando escrevemos esse código complexo, muitas vezes a code review dele é recusada por ser impossível de entender, ou pior, a pessoa que está conduzindo, entende da linguagem e do sistema tão bem ou melhor que quem escreveu o código em questão e por essa razão pede coisas que são ainda mais complexas como forma de provar um ponto o que leva ou a simplificação, ou a uma batalha de egos infindável onde toda a equipe perde.


Nomenclatura

É possivelmente a coisa mais difícil que precisamos fazer quando programando, nomear coisas. Feliz ou infelizmente não temos o privilégio de grandes pesquisadores que nomeiam algo em homenagem a si mesmos ou a outros, temos a árdua tarefa de nomear algo de forma que todos que encontrem esse bloco de código entendam. Segue aqui algumas ideias e práticas que podem te auxiliar:


Orientação a Objetos

Não vou me aprofundar muito nesse post nos pilares da Orientação a Objetos e suas definições (isso é material para outro post), mas muitas vezes encontramos bases de código que não seguem esse padrão e por essa razão são menos eficientes ou mais repetitivos do que poderiam ser. No meu post anterior sobre SOLID, abordei alguns desses pontos, e acredito que valha a leitura dele como um complemento para esse, mas no momento, quero focar nos seguintes pontos:


Sobrecarga de métodos

Ao criarmos um método, podemos perceber que sua assinatura não é suficiente para resolver um problema. O exemplo a seguir é também um preludio para o padrão Repository, que logo abordaremos.

O padrão “Repository” também conhecido como “Selector” é um padrão que abstrai as chamadas ao banco de dados, centralizando todo o código em uma classe, de forma que caso a modelagem do objeto seja alterada, tenhamos apenas um ponto de alteração no código, evitando grandes erros em diversas classes. Falaremos mais sobre em momento oportuno.

Ao criarmos uma classe nesse padrão podemos lidar com dois tipos de entrada de dados para alterar no banco, sendo eles dados que formam um único registro ou que formam uma lista de registros. Para evitar criar dois métodos com nomes diferentes mas com a mesma funcionalidade, podemos criar dois métodos com o mesmo nome e uma assinatura diferente, de forma que o sistema possa receber os diferentes tipos de entrada e trabalhar de forma adequada com os dois. Colocando esse exemplo em código:


Herança

Esse tema é extremamente complexo e gera muitas discussões, então como esse não é nosso tópico, mais uma vez não irei me aprofundar. O ponto importante, é o que podemos ver no exemplo de código acima. Criando uma classe abstrata de Repository, permitimos criar classes que estendam essa funcionalidade para objetos específicos, permitindo a utilização dos seus métodos sem a necessidade de reescrever os mesmos em todas as classes do padrão.


Padrões de Projeto

Conhecidos como Design Patterns, são blocos de código reutilizáveis que solucionam problemas comuns quando falamos de software orientado a objetos. O livro “Padrões de Projeto” escrito pelo “gang of four” apresenta vinte e três padrões diferentes, divididos em três categorias, sendo elas:

  • Padrões de criação

  • Padrões estruturais

  • Padrões de comportamento

Esses padrões simplificam a solução de problemas como acesso ao banco de dados, criação de objetos, transferencia de informações entre pontos diferentes do sistema e adaptação dessas informações. Abordaremos aqui alguns desses padrões, como uma introdução a um post futuro, se aprofundando mais em alguns e/ou explicando outros.


Repository

Tratamos dele mais acima hoje e agora vamos para a sua implementação completa:

Iniciamos com uma classe abstrata

E estendemos com os objetos e campos que tivermos necessidade, por exemplo:

Podemos ainda melhorar a nossa classe abstrata utilizando ao redor dos comandos de Database uma condicional que cheque o tipo do objeto e se é permitido criar, alterar ou deletar o mesmo.


Builder

Esse é um dos meus preferidos, ele permite simplificar a criação de objetos complexos de maneira simples e encadeada. Ele também facilita a criação de objetos com diferentes configurações ou com diferentes etapas em sua criação. Um exemplo seria o seguinte:

E sua utilização seria:

Fica como exercício para você que está lendo utilizar os padrões Repository e Builder em conjunto.


Enricher

Esse é um padrão que não foi descrito no livro de padrões de projeto, mas é bastante comum quando tratamos de Salesforce. Ele é uma variação do Builder, normalmente utilizada em triggers para enriquecer dados, populando campos que não foram preenchidos por qualquer razão. Em resumo, é uma alteração mais na nomenclatura no intuito de especificar quando a classe será utilizada.


Validator

Como o nome sugere, é uma classe que existe com o intuito de validar informações. O exemplo abaixo valida se um CPF é valido.


Filter

Outro padrão com o nome muito sugestivo, que tem a função de filtrar dados e retornar aqueles que passam pelo filtro. Por exemplo, um filtro em Contas (Account) poderia ser feito da seguinte maneira:

Existem formas de deixar essa classe mais simples, e novamente acredito que seja interessante deixar isso como atividade para você que está lendo, como uma forma de treinar e colocar em prática o que foi visto mais acima. Veja que a lógica é a mesma nos dois casos:

  1. O método recebe uma lista de Contas.

  2. Cria uma lista de contas filtradas.

  3. Itera pela lista.

  4. Se a Industria ou País for igual ao que está sendo validado, adiciona o valor a lista filtrada.

  5. Retorna a lista para quem chamou a validação.

Depois me conta se acha que deixar essa classe mais genérica é ou não uma boa ideia, e a razão!!

Futuramente iremos falar de outros padrões, então se quiser, sinta-se a vontade para enviar aqui embaixo ou no meu LinkedIn (ou até WhatsApp, caso tenha meu número) sugestões de quais padrões devemos ver ou nos aprofundar.


Testes

Fazendo um gancho para o meu último post, testes são além de importantes, uma obrigação imposta pela própria Salesforce. Nossos testes devem, em nenhuma ordem de importância:

  • Cobrir ao menos 75% da classe (idealmente mais)

  • Cobrir casos de falha

  • Cobrir ações individuais e em massa

  • Restringir modos de usuário utilizando runAs (mais um tópico para outro post)


Qualidade (PMD)

PMD é uma ferramenta de análise de código fonte que tem o intuito de garantir que melhores práticas sejam utilizadas e nos auxilia a evitar falhas de segurança ou dificuldade de leitura e entendimento do código. Quando utilizado de forma correta, ele pode desde alertar o desenvolvedor até bloquear deploys para ambientes externos ao ambiente de desenvolvimento.

Entre outras regras, o pmd checa:

  • Que comandos de Assert em classes de teste verifiquem se o método tem o parâmetro de texto falando sobre a asserção.

  • Classes de teste tenham a anotação @isTest.

  • Que não existem operações de DML em construtores.

  • Blocos “catch” não estão sem conteúdo.

  • Que operações demasiadamente custosas não sejam utilizadas em loop.

Por este post é isso, espero sinceramente que ele te ajude a melhorar a qualidade do seu código, e prometo que logo virão posts mais densos em relação a código e quem sabe até mesmo arquitetura. Acredito que seja importante tratar desses pontos de como fazer algo, ou como fazer de uma maneira mais eficiente, mas assumo que tenho falhado na parte de escrever conteúdo mais acerca de código mesmo (não precisa jogar na cara que eu só posto quando os planetas se alinham, eu sei que falho nisso, mas estou tentando melhorar, juro) então por favor enviem por qualquer caminho que acharem melhor sugestões do que abordar aqui que será um prazer falar sobre.

Obrigado pela leitura!

 
 
 

ความคิดเห็น


© 2023, BrazucaForce - Todos os direitos reservados

Políticas de Privacidade

bottom of page