Práticas que tornarão seu código melhor


Práticas que tornarão seu código melhor

No Women Techmakers Membership recebemos dicas semanais sobre diversos assuntos, e com base no artigo 5 practices that will make your code better, que foi indicado um tempo atrás, venho aqui sugerir algumas práticas.

  1. Programação Defensiva:

Essa prática tem como objetivo aplicar um conjunto de técnicas para ter estabilidade e segurança em um software, promovendo um código que funciona em qualquer circunstância não prevista. Além da estabilidade provida, caso seja necessário aplicar alguma manutenção será muito mais simples.

O mandamento de uma boa Programação Defensiva pode ser listado da seguinte forma:

  • Liberar os Recursos após uso: Dependendo da linguagem e da funcionalidade de um método, é necessário finalizar ele corretamente, senão ele pode consumir recursos de hardware e servidor, caso contrario, poder acabar emitindo um erro não tão esclarecido.
  • Mantenha um estilo de codificação uniforme, ou seja, respeite o Boilerplate (Estruturação de Arquivos e Pastas) da linguagem e do projeto, mantenha a endentação e tamanho dos espaços padronizados, e para finalizar siga o padrão de escrita do projeto ao nomear qualquer coisa (Classes, Variáveis, Arquivos, Métodos e etc.).
  • Valide a entrada do usuário. Se o input deve receber uma string, ele TEM que receber uma string. Essa prática ajuda a proteger a entrada do banco de dados e você sempre ter certeza o que você está recebendo daquele input.
  • Comente o seu código (com moderação), para explicar por que as coisas são feitas e não como são feita (se você sentir que precisa explicar como algo é feito, você deve considerar refatorar o código).
  • Controle as exceções e retorne erros mais legíveis. As vezes a linguagem pode lançar uma exceção que não pode ser capturada ou legível, por isso a importância de controlar as exceções, seja de forma genérica ou com um try catch. Não esqueça de padronizar os seus tratamentos de erros.
  • Certifique-se de que cada método, classe, variável e propriedade, possuam um objetivo claro e único, um nome claro com uma intenção clara (que corresponda à implementação). Ele deverá ser curto e conciso no nome e no caso de um método, deverá possuir um código sucinto e não ter nenhuma ação inesperada (isto é, não deve realizar operações imprevistas). Exemplo:
Função somar(x){ retorna: x - 1}

No exemplo está claro que o método possui a função de somar logo ele não pode subtrair.

  • Seu código deverá ter um contrato claro, é possível programar por contrato (Design by Contract), esse tipo de abordagem tem como objetivo prescrever e definir os métodos formais, interfaces e etc…
  • É testável? É possível realizar testes em seu código? Um código bem estruturado e definido, é possível realizar testes unitários e de integração com muita facilidade.
  • Utilize a modelagem de Orientação a Objeto, com sabedoria, pois assim você não terá vazamentos (os detalhes internos e as limitações devem ser mantidos internos), e seu código estará protegido de manipulações inesperadas por parte de outros algoritmos.

2. Realize Testes:

Essa prática tem como objetivo reduzir o número de erros de quando o seu código estiver em produção e torna menos arriscado mudar e refatorar o código, e também impede que regressões de versionamento se repitam. Quando feito corretamente, também pode fazer você escrever um código melhor.

fonte: http://www.softdesign.com.br/blog/testes-automatizados-parte-1-os-tipos-de-testes/

Olhando a imagem acima é possível ver que existem inúmeros tipos de teste e cada um deles tem uma finalidade diferente, irei falar sobre os dois que são mais comentados:

  • Teste de Unidade (Teste Unitário): Ele testa de maneira isolada sem considerar qualquer outra coisa a não ser se aquela unidade está tendo o comportamento correto, esse tipo de teste é muito usado para validar se o método está passando por certas entradas e se a saída é a esperada. Exemplo:
Função somar(x){ retorna: x + 1}
O teste dessa unidade seria:
Função_Teste somar(1){ Se retornou 2: mande um OK, senão mande um Failed}
  • Teste de Integração: Ele testa a comunicação e os usos dos pacotes, ou seja, ele testa tudo que for necessário para o código funcionar bem que seja externo. Exemplo:
Função Busca de Coelhos no Banco de Dados(coelho){ Dou um Search no banco de Dados até achar o coelho}
O teste de integração seria:
Função_Teste Busca de Coelhos no Banco de Dados(coelho rosa) {Se consegui estabelecer uma comunicação e achei o coelho rosa: mande um OK, senão mande um Failed}

A diferença entre os dois é que nos teste de unidade focamos apenas nas funções internas do nosso código, enquanto o teste de integração foca em testar a comunicação externa com a interna.

Você pode automatizar os seus testes, basta você procurar algum pacote ou ferramenta para a linguagem que você usa. Para saber mais sobre as práticas e sobre o assunto acesse: Test Driven Development: TDD simples e prático.

3. Princípios S.O.L.I.D:

Quando falamos desse princípio logo pensamos em como aplica-lo em Programas Orientado a Objetos. S.O.L.I.D é um acróstico para:

  • S = Single-Responsibility Principle (Princípio de Responsabilidade Única)

Esse princípio nos ensina que as classes devem ter uma responsabilidade única.

  • O = Open/Closed Principle (Aberto para Extensão, Fechado para alteração)

Nessa parte cita que as classes devem poder estender o seu comportamento sem que haja a necessidade de alterar o seu código.

  • L = Liskov Substituition Principle (Substituição de Liskov)

Esse principio nos ensina que as instâncias de um objeto deve poder ter a possibilidade de ser substituída por instâncias de seus subtipos, sem que o sistema deixe de funcionar corretamente.

  • I = Interface Segregation Principle (Segregação de Interfaces)

A segregação de Interface explica possuir várias interfaces que são especificas, são melhores do que uma única interface para uso geral.

  • D = Dependency Inversion Principle (Inversão de Dependências)

A inversão de dependência significa que as classes devem depender de abstrações e não de coisas concretas.

4. Injeção de dependência / Inversão de controle:

Por estarem no mesmo tópico você leitor pode achar que são a mesma coisa, mas são coisas diferentes, a injeção de dependência é um sub-tipo da inversão de controle.

  • Injeção de Dependência (DI):

É uma técnica utilizada para injetar em um objeto suas dependências. Injeção de Dependências é uma forma de se obter a Inversão de Controle. Não irei descrever com mais detalhes os 3 tipos de DI, porém, elas são Injeção de Interface (Interface Injection), Injeção de Setters (Setter Injection) e Injeção de Construtor (Constructor Injection).

  • Inversão de controle (IoC):

Consiste em mudar o fluxo de controle do programa, ao invés do desenvolvedor determinar quando um procedimento será executado ele apenas determina qual procedimento deve ser executado para um determinado evento.

As vantagens para usar o IoC/DI são:

— Desacopla os códigos, que por sua vez aumenta a reutilização, torna mais fácil testar e permite gerenciar a instanciação de objetos em um nível mais alto. 
 — Focaliza um módulo para tarefa projetada.
 — Ele evita efeitos colaterais ao substituir um módulo. 
 — Se possui um código testável.
 — Promove um bom design Orientado a Objeto.

5. Imutando o seu código

E nessa dica final, estamos pegando um aspecto do paradigma de programação funcional. O aspecto baseia-se em que você nunca deve ser capaz de mudar um objeto. Se um objeto precisa ser alterado, ele deve ser recriado.

Para isso que tal usarmos constantes? Ou criar um método para manipular o elemento?

Os benefícios que se pode obter é :

— Ter objetos seguros para thread (Thread Safe). 
 — Prevenção de se ter objetos com estados inválidos. 
 — A imutabilidade torna mais fácil a escrita, e lhe faz considerar o uso e a razão sobre o código. 
 — A imutabilidade torna mais fácil paralelizar o seu programa, pois não há conflitos entre objetos.
 — As referências a objetos imutáveis ​​podem ser armazenadas em cache, pois não vão mudar.

Espero que vocês gostem e usem algumas dicas.