Você está na página 1de 8

Boas práticas de programação e a Importância dos testes http://www.devmedia.com.br/articles/viewcomp_forprint.asp?

comp=31163

www.devmedia.com.br
[versão para impressão]
Link original: http://www.devmedia.com.br/articles/viewcomp.asp?comp=31163

A vida de um programador não é fácil. A tecnologia é algo que não para de evoluir e a cada dia surge uma forma diferente de
escrever um código. A carreira de um profissional de informática é algo de sua responsabilidade.

O código produzido por esse profissional também é de sua responsabilidade. Um bom código não é somente aquele que é funcional,
mas também aquele que não tem valores exorbitantes para ser mantido. A maior parte dos programadores não gostam de
alterar códigos mal escritos. Isso é algo que traz muita frustração e muitas vezes um retrabalho desnecessário.

Infográfico 1O que é programação

1 de 8 04/03/2018 19:07
Boas práticas de programação e a Importância dos testes http://www.devmedia.com.br/articles/viewcomp_forprint.asp?comp=31163

2 de 8 04/03/2018 19:07
Boas práticas de programação e a Importância dos testes http://www.devmedia.com.br/articles/viewcomp_forprint.asp?comp=31163

Um código limpo deve ser:

Simples: código fácil de entender;


Direto: vai direto ao ponto, não dá “voltas" para atingir seu objetivo;
Eficiente: código que faz o que é proposto;
Sem duplicidade: não faz o que outra parte do código já faz;
Elegante: porque é diferente dos outros códigos;
Feito com cuidado: quem fez teve preocupação em produzir aquele código.

Antes de falarmos sobre como fazer para atingir esse nível de qualidade, vamos falar um pouco sobre testes.

Construir um software não é somente escrever código e vê-lo funcionar, é você saber que aquele código será manutenível e que
outras pessoas vão alterá-lo.

Para isso, teste é fundamental! Você tem que ser responsável por aquilo que escreve e saber que seu sistema tem que continuar
funcionando. Neste contexto, temos a primeira dica sobre um código limpo: "Toda linha que você escrever deve estar testada e ponto
final !"

Muitas empresas veem testes como gastos maiores no projeto, o que de fato acontece, porém a qualidade do software produzido é
algo significante. Quando não se produz teste automatizado, a quantidade de testes manuais são maiores e muitas vezes o custo
desses testes também é maior.

Relacionado: Engenharia de Software

Métodos, nomes de variáveis e etc. devem possuir nomes que significam alguma coisa em relação ao seu objetivo. Os nomes
utilizados devem responder todas as questões a seguir:

Porque existem?
O que fazem?
Como são usadas?

Vamos imaginar que um sistema de um motor de um carro tenha um método com o nome de “run” ao invés de “acelerar”. Se você
pegar um código com esse nome você terá que estudar todo o método para saber o que ele faz.

Algo muito comum encontrado nos códigos é o tipo de declaração apresentado na Listagem 1.

Listagem 1. Exemplo de declaração

public class NotaFiscal {


private Date d1;//Data da compra
private Date d2;//Data de vencimento
private boolean validaDatas(){
//Valida se data do vencimento é maior que a data de compra
if(d1.after(d2))){
return true;
}
return false;
}
//getters e setters
}

Se um nome de classe, método ou atributo requer um comentário, ele não está revelando sua real intenção.

Quando colocamos uma linha em nosso código com um comentário ao lado não estamos dando o nome correto ao atributo ou método.
O código quando bem escrito deve ser algo que seja de fácil leitura, algo que uma pessoa leiga conseguiria ao menos saber o que o
mesmo faz. Os nomes utilizados devem ser pronunciáveis, algo que você entenda.

3 de 8 04/03/2018 19:07
Boas práticas de programação e a Importância dos testes http://www.devmedia.com.br/articles/viewcomp_forprint.asp?comp=31163

Observe no exemplo da Listagem 2 como essa prática torna o código mais fácil de ser entendido.

Listagem 2. Exemplo de declaração considerando boas práticas

public class NotaFiscal {

private Date dataCompra;


private Date dataVencimento;

private boolean isDataVencimentoMaiorDataCompra(){

return dataCompra.after(dataVencimento);

//getters e setters
}

A notação Húngara visa facilitar o reconhecimento do tipo de variável em um programa colocando em seu nome um sufixo
descrevendo seu tipo (ver Listagem 3). Entretanto, com o advento de novas linguagens, técnicas mostradas aqui e testes
automatizados, a notação húngara se mostra desnecessária.

Existe uma certa tendência para a criação de classes e métodos menores de modo que as pessoas possam ver onde cada variável que
estão usando foi declarada. Além disso, os testes indicam os tipos e maneiras de usar, validando o comportamento esperado do
método.

Listagem 3. Exemplo de uso de notação húngara

public class Pessoa {

private String nomeString;

// Não existe aqui a necessidade de se colocar a palavra 'String', pode-se somente ficar 'nome'

//getters e setters
}

Nome de classes devem ser substantivos e não conter verbos. Já nomes de métodos devem conter verbos pois eles indicam ações.

A regra para métodos é: “A primeira regra dos métodos é que eles devem ser pequenos. A segunda regra é que eles devem ser
menores ainda.”

Métodos e classes menores são mais fáceis de ler e entender, além de manter é claro. Segundo o livro, podemos considerar as
seguintes métricas:

· Métodos <= 20 linhas;

· Linha <= 100 caracteres;

· Classe = 200 a 500 linhas.

Claro que toda regra tem sua exceção. Se você tem uma classe que vai precisar de mais linhas, um método que também precise de
mais linhas, isso não é um problema.

“Métodos e funções devem fazer somente uma coisa, fazê-la certa e somente fazê-la”.

Poderíamos analisar essa frase como um princípio da coesão no seu código. Muitas vezes não é fácil saber se aquele método está
fazendo somente uma coisa. Uma dica para isso é: você deve tentar extrair parte do seu código para um método, se você conseguir é
porque aquele seu método realmente não está tendo uma função apenas.

Imagine que você tenha um método onde quiséssemos mostrar os detalhes de um usuário:

private void mostrarDadosUsuario(Usuario usuario){


mostrarCabecalhoUsuario();
System.out.print(“Nome: “, usuario.getNome());
System.out.print(“Sobrenome: “, usuario.getSobrenome());
}

4 de 8 04/03/2018 19:07
Boas práticas de programação e a Importância dos testes http://www.devmedia.com.br/articles/viewcomp_forprint.asp?comp=31163

Neste exemplo, as linhas do System.out.print são os detalhes do usuário. Mas será que isso não ficaria melhor escrito se estivesse de
acordo com o código da Listagem 4?

Listagem 4. Separando métodos

private void mostrarDadosUsuario(Usuario usuario){

mostrarCabecalhoUsuario();
mostrarDetalhesUsuario();

private void mostrarDetalhesUsuario{


System.out.print(“Nome: “, usuario.getNome());
System.out.print(“Sobrenome: “, usuario.getSobrenome());
}

Se um dia você quiser apenas listar os dados de um usuário ficará mais fácil. Agora temos os métodos separados. Essa prática
também é um bom exemplo do tipo de refatoração chamada “Extract Method”.

Um outro item que deve ser observado é a quantidade de parâmetros de um método. Você deve ter uma justificativa muito boa para
ter uma quantidade tão grande de parâmetros em um método.

Um agravante de um método com vários parâmetros é a dificuldade de se testar uma vez que você deverá testar todas as
combinações possíveis.

Outra situação a que você deve estar atento é com um método que informa que irá fazer uma determinada ação e faz outra. Observe
a Listagem 5.

Listagem 5. Métodos com objetivos mal definidos

public boolean verificarSenha(String senha){


if(senha.equals(“zzz”)){
Session.initialize();
return true;
}
return false;
}

O objetivo do método é verificar a senha, porém, se a senha estiver correta o mesmo inicia uma sessão, ou seja, o método já não tem
a coesão esperada, pois possui duas responsabilidades.

Uma solução melhor para esse cenário pode ser observada na Listagem 6.

Listagem 6. Ajuste do objetivo do método

if(verificaSenha(“zzz”){
Session.initialize();
}

public boolean verificarSenha(String senha){


if(senha.equals(“zzz”)){
return true;
}
return false;
}

Comentários, apesar de importantes, podem trazer desinformação. Por que podemos afirmar isso? Alguém conhece programadores que atualizam
comentários? Há vários códigos com vários comentários que não serviam para nada e, pior, confundiam. Se um método ou uma classe estiver bem
escrito, a importância do comentário é minimizada.

Outro ponto importante, um comentário não irá esconder um código ruim. Observe o exemplo a seguir:

Date d1;

Esse código já está ruim, de nada adianta mudarmos para:

Date d1; //dia da semana

Esse comentário não irá se propagar para todo o código e sempre que você se deparar com uma linha como “d1.after(d2);" você vai continuar não
entendendo o propósito do código.

5 de 8 04/03/2018 19:07
Boas práticas de programação e a Importância dos testes http://www.devmedia.com.br/articles/viewcomp_forprint.asp?comp=31163

Podemos tentar colocar uma regra nisso. Muitas vezes quando se comenta um código, pode ser que o mesmo precise ser refatorado. Lembra dos
exemplos anteriores onde “d1” passou a ser “dataCompra” ? Com essa mudança seu código pode ser entendido por todos e se fizermos essa refatoração
o código passa a não precisar mais de comentário.

Observe agora o exemplo a seguir:

//Verifica se o usuário tem direito ao benefício


if(usuario.getIdade() > 10 && usuario.getIdade() < 20){
….
}

Observe agora o exemplo ajustado na Listagem 7.

Listagem 7. Eliminando o comentário do código

if(isUsuarioTemDireitoAoBeneficio(usuario)){
….
}

private boolean isUsuarioTemDireitoAoBeneficio(Usuario usuario){


if(usuario.getIdade() > 10 && usuario.getIdade() < 20){
return true;
}
return false;
}

Note que tiramos o comentário, melhoramos o código e o tornamos mais legível. Agora a leitura do código é suficiente para saber o que ele realmente
faz.

Outro tipo de comentário que deve ser evitado é apresentado no exemplo a seguir:

private boolean isUsuarioTemDireitoAoBeneficio(Usuario usuario){ if(usuario.getIdade() > 10 && usuario.getIdade() < 20){
return true; //Retorna verdadeiro
}
return false; //Retorna falso
}

O return do método é lógico, não há necessidade de indicar o que o mesmo está retornando.

Em relação a comentários, podemos dizer que: “Qualquer comentário que faça você olhar para outras partes do seu código para entendê-lo não valem
os bits que consomem.”

Por outro lado, existem momentos em que o comentário é importante. Digamos que você tenha um trecho em seu código que vai demandar um tempo de
processamento alto ou a disponibilidade de um recurso. Nesses casos, comentários acabam sendo úteis.

Algumas vezes também não se consegue colocar um nome em um método que explique o porquê o desenvolvedor tomou aquela decisão.

“Formatação é importante, pois se trata de comunicação.”

Temos que considerar que o código é a maneira que a equipe de desenvolvimento vai se comunicar. Uma pessoa não gostaria de receber uma carta
cifrada onde tivesse que interpretar o que está escrito nela, podemos pensar assim na hora de escrever um código.

Outra ponto importante é que se você pega um código bem estruturado, você vai querer mantê-lo bem estruturado. É ruim para qualquer desenvolvedor
ter acesso a um código sem formatação, sem endentação e ter que fazer sua leitura como se fosse um texto sem qualquer pontuação.

Além disso, métodos com conceitos relacionados devem ficar verticalmente próximos e a ordem dos métodos deve criar um fluxo de leitura melhorando
a legibilidade do código.

Uma boa endentação é fundamental, mas não podemos ter muitos níveis. Observe como o trecho a seguir poderia se tornar confuso caso a lógica
implementada fosse complexa:

if(a>1){
if(b>1){
if(c>1){
if(z>1){

}
}
}
}

Tratamento de erros

"Quando estamos programando devemos tratar os possíveis erros que nossa aplicação poderá lançar, as coisas podem dar errado e temos que estar

6 de 8 04/03/2018 19:07
Boas práticas de programação e a Importância dos testes http://www.devmedia.com.br/articles/viewcomp_forprint.asp?comp=31163

certos que nosso código fará o que deve fazer."

Tratamento de erro é de responsabilidade do desenvolvedor. É preciso garantir que o código vai ter um tratamento para cada situação. Prefira lançar
uma exception ao invés de retornar um código de erro. Estes retornos desorganizam a chamada do método e pode-se facilmente esquecer de verificá-los.

Dentro do seu método você já pode ver o erro que está sendo retornado e tratá-lo ali. Defina o fluxo do método separando as regras de negócio de erros
ou outras situações. Para seus erros, crie mensagens informativas mencionando a operação que falhou e o tipo de falha.

Procure utilizar exceptions para situações inesperadas, por exemplo: seu código está lendo um arquivo e a rede se tornou indisponível.

TDD nada mais é que o desenvolvimento guiado por testes. As três regras do TDD são:

Você não pode escrever um código até que tenha criado um teste falhando;
Você não pode escrever mais teste do que seja suficiente para falhar;
Você não pode escrever mais código do que o suficiente para passar no teste que está falhando.

Assim, se você tiver que testar se um CPF é válido, por exemplo, você deve criar alguns testes tais como:

se o CPF for em branco;


se o CPF estiver com menos caracteres.

Os testes devem considerar as características F.I.R.S.T:

*F (Fast): deve ser rápido. Testes demorados tiram a motivação dos profissionais responsáveis por sua execução;
*I (Independent): não podem depender um do outro pois se um falha o outro vai falhar também;
*R (Reapetable): executando mais de uma vez eles devem retornar sempre o mesmo resultado;
*S (Self-Validating): devem se autovalidar;
*T (Timely): devem ser feitos antes do código.

Escrever um bom código muitas vezes pode não parecer uma missão tão simples. Considere o trecho de código a seguir:

private boolean isStringVazia(String texto){


if (!StringUtils.isNullOrEmpty(texto) && !texto.equals("")) {
//...
}
}

Concorda que o "!texto.equals("")" não serve para nada? Se fizermos a refatoração a seguir obteremos o mesmo resultado:

private boolean isStringVazia(String texto){


if (!StringUtils.isNullOrEmpty(texto)) {
//...
}
}

Agora, digamos que ainda assim estivéssemos com receio de fazer essa refatoração. Neste caso, a presença de um simples teste unitário poderia eliminar
a dúvida referente ao fato da funcionalidade continuar desempenhando seu papel corretamente.

A refatoração é uma das melhores práticas para melhorarmos nosso código. Seu código pode ser eficaz, ou seja, fazer o que se deseja, mas também pode
ser eficiente, fazer o que se deseja da melhor maneira possível.

Links Úteis

W3Schools - Tutorial de HTML5:

W3C - HTML5:

Wikipédia - HTML5:

Saiba mais sobre programação ;)

Introdução a Programação:

Conheça nosso Guia de Referência de Introdução à Programação. Aprenda a programar na DevMedia e torne-se um profissional preparado para o mercado. Acesse!

DevCast: Programação: O que é uma variável?:

Neste DevCast conversamos sobre o que é uma variável e qual o seu papel, permitindo assim que você crie o seu primeiro programa: um aplicativo que recebe um nome e imprime na tela uma

mensagem de boas vindas.

Lógica de Programação:

Neste curso veremos uma introdução a algoritmos, utilizando como linguagem de apoio o Portugol.

por Leandro Tavares


Engenharia de software lover

7 de 8 04/03/2018 19:07
Boas práticas de programação e a Importância dos testes http://www.devmedia.com.br/articles/viewcomp_forprint.asp?comp=31163

8 de 8 04/03/2018 19:07

Você também pode gostar