O Carinha de TI

Boas práticas de programação Java

Essa publicação está 100% relacionada ao Hangout Gratuito da Escola Linux – Boas Práticas de Programação com Java que você pode assistir nesse vídeo:

Conteúdo abordado:

  • Clean Code
  • Código manutenível
  • Escrevendo um bom código segundo Uncle Bob
    • Nomes significativos
    • Evite a notação húngara
    • Classes e métodos
    • Comentários nos códigos
    • Formatação e refatoração

Clean Code

Robert Martin escreveu o livro Clean Code, ele nos deixou a seguinte frase:

“Até um código ruim pode funcionar, mas se o código não for limpo, ele pode trazer uma organização de desenvolvimento a ficar de joelhos”

Bom, Nosso hangout foi praticamente baseado no Livro Clean Code, o livro é de fácil interpretação, ele é muito bem escrito e explicativo, aborda temas bastante interessantes. O livro trata de tópicos como: código limpo, nomeações de classes, variáveis, refatorações e muito mais.

Código manutenível

Código manutenível é o poder que o código tem de ser passível de ser dado manutenção ou de ser mantido.

Por meses eu não sabia o que eu escrevia, e até hoje eu procuro melhoras, cada dia você vê acha um jeito melhor para escrever um código.

Se, você pega um código que está escrito assim:

i = escolaLinux.getId();

E ainda o programador fez o favor de sair copiando e colando pela classe. A primeira pergunta a se fazer é: O que diabos é “i”? Nesse trecho estamos vendo que é escolaLinux.getId(); mas toda vez eu vou ter que ficar voltando o código para ver o que está sendo atribuído para “i”?

Então podemos trocar esse “i” por idEmpresa, por exemplo. Outro caso similar a esse é o uso de métodos, por exemplo se você, programador, escreve o método vai();

Eu te pergunto, para onde? Por que não editarEmpresa(), salvarEmpresa()?

Detalhe, você ainda pega o método cópia e cola e muda trechos do código dentro, (eu fiz muito isso no início, quando iniciei em programação).

Certamente um dia, um programador vai pegar esse código e vai te xingar de todos os nomes possíveis, ou pior e te chamar de “usuário” ‘piada 🙁 ‘ .

Tem uma frase de Martin Fowler que é um autor conhecido na área de arquitetura de software, que dizia:

“Qualquer um pode escrever um código que o computador entenda, mas o verdadeiro desenvolvedor escreve código que outro desenvolvedor entenda. ”

Escrevendo um bom código segundo Uncle Bob – Nomes Significativos

Vamos pegar o exemplo do método vai();

Nomes de métodos, variáveis devem dizer alguma coisa, você precisa olhar exatamente onde você está e saber o que ela quer dizer, sem precisar seguir a variável ou ler o método para entender o que ele faz.

Vamos ao exemplo:

Date d = new Date();

Date d2 = new Date();

if(d.afer(d2)){

//…

}

Agora me responda o que é isso? O que é d? o que é d2?

Mas você é um programador esperto! Certo?

Ai você vai e decide comentar a variável para que você ou outros entendam o que foi feito ai vc faz:

Date d = new Date(); //Dia do vencimento

Date d2 = new Date();  //Data atual

if(d.afer(d2)){

//…

}

Evite programar dessa forma, veja como seria uma boa forma para nomear as variáveis:

Date dataAtual;

Date diaDoVencimento;

if(diaDoVencimento.after(dataAtual)){

//…

}

Ficou ou não ficou mais fácil de ler?

Uncle Bob diz que os nomes devem ser significativos e devem dizer basicamente:

  • Por que existem ?
  • O que faz ?
  • Como é usado ?

Assim o nome deve dizer seu objetivo, se o nome requer comentário, então ele não está dizendo seu objetivo. Imagine outro exemplo, que por sinal, confesso que eu já fiz isso muito, sabe por quê?

Sempre pensamos, eu vou lembrar, primeiro, com meses você não vai lembrar e segundo e se outro programador ler?

private String getELNSUsuario(){//…}

Então se você tem ou sequer pensou em ter essa pratica, não faça mais

Veja como fica melhor

private String getEscolaLinuxNomeESobrenomeDoUsuario{//…}

Mas ficou grande né? Sim, porém o nome se tornou pronunciável, esqueçam essa prática de economizar palavras, escreva o quanto for possível para que seu código seja entendido.

Notação Húngara

Gente, Evite deixar explicito o tipo de Dado na variável, isso pode atrapalhar, as vezes usamos um array onde se coloca que é um list e vice e versa.

Então utilize somente “arquivos”, não interessa se é uma lista ou um array, interessa que você tem os lançamentos que precisa.

/* Todos tem a lista de arquivos */
List listaDeArquivos;
ArrayList arrayDeArquivos;
File[] vetorDeArquivos;

String strNome;

//List, ArrayList, File[], etc
// Não importa o tipo, importa que tenho a lista
List arquivos;
String nome;

Classes e Métodos

Segundo Uncle Bob, os nomes de classes não devem conter verbos e sim ser substantivos, já os métodos devem conter verbos, mas por quê? É Simples, os verbos são ações, ações que executam alguma coisa, por isso a presença de verbos nos métodos.

A regra para métodos é bem simples, segundo Uncle Bob:

Métodos e classes devem ser pequenos, pois quantos menores forem mais fáceis de entender e de manter claro.

Então o que nós temos nas regras?

Métodos <= 20 linhas

Linha <= 100 caracteres

Classe = 200 a 500 linhas

Não veja isso como uma regra tipo padrão, mas sim como um norte, uma bússola, é claro que você pode precisar que os métodos tenham mais de vinte linhas, ou uma classe passe das 500 linhas.

Vamos ver um exemplo de como podemos fazer isso com métodos, agente quebra o método em outros métodos.

private void mostrarDadosEmpresa(Empresa empresa) {
System.out.println(“ID: ” + empresa.getId().toString());
System.out.println(“Razao Social: ” + empresa.getRazaoSocial());
}

Nesse método estamos imprimindo no prompt os dados da empresa, digamos, por exemplo, que isso fossem muitos dados, e até mesmo precisássemos só da metade.

Uncle Bob diz:

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

Ai galera para você saber se você está fazendo a coisa certa no método é simples, você tenta extrair parte do seu código para um método, se você conseguir então o método realmente não está tento uma só função.

Então o que a gente faz?

Vamos criar dos métodos, um para mostrar o ID e outro para mostrar a razão social e dentro do método chamamos os dois métodos, assim, teremos métodos menores, e ainda, podemos imprimir separadamente os dados.

OBS: Não vemos lógica um método para imprimir ID e outro para razão, lembre-se esse exemplo é apenas para nível de entendimento e estudo. Na prática esse exemplo não faz muito sentido.

Isso é um método de refatoração chamada “Extract Method

Parâmetros

Outra pratica que acontece muito é a questão de quantidade de parâmetros envolvidas num método

Por exemplo:

        montaPerfil(1, 2, 1, 1, 1, 1, “”, 1, 2, 2, 2, 2, “”, “”, “”, 2, 1, 2, 3);

Como saber o que se pede? Ai você tem que entrar no método e descobrir, quando você chega lá, olha só, a declaração das variáveis é tudo estilo o Date d;

Você precisa de uma boa justificativa para ter uma quantidade tão grande de parâmetros em um método. Outra coisa que temos que tomar cuidado são os métodos que dizem uma coisa e fazem outra, pode até fazer o que está dizendo, mas junto realiza outra ação.

Por exemplo:

Temos o método verificaSenha, vamos ver aqui o que ele faz…

private static boolean verificaSenha(String senha) {
if (senha.equals(“EscolaLinux”)) {
iniciarlizarSistema();
return true;
}
return false;
}

Eu quero verificar uma senha, então se a senha estiver correta, ele inicializa uma seção, ou seja, o método já não está com sentido esperado, e ainda está com duas responsabilidades.

Se eu quisesse apenas verificar uma senha? Toda vez seria obrigado a iniciar o sistema?Agora, vejam como seria a forma mais coesa:

if (verificaSenha(“EscolaLinux”)) {
iniciarlizarSistema();
}

private static boolean verificaSenha(String senha) {
if (senha.equals(“EscolaLinux”)) {
return true;
}
return false;
}

Aqui nos temos um if que chama o método que verifica a senha, e se estiver tudo correto chama o método q inicializa, e se eu quisesse posso apenas verificar a senha. De acordo com o princípio command query separation métodos devem fazer algo ou retornar algo, mas não as duas coisas ao mesmo tempo.

Comentários

Muita atenção com comentários, pois comentário pode acabar trazendo informação errada.

Sabe por quê? Você conhece alguém que atualiza os comentários? É muito difícil, eu já passei por vários códigos que tinham comentários que não serviam de nada, e acredite se quiser, comentários que eu mesmo escrevi depois de dias ou meses chegava no trecho e me pergunta que “danado” eh isso?

Pense bem, se a classe, ou o método estiver bem escrito o comentário vai passar despercebido. Um comentário jamais vai esconder um código ruim, lembra do Date d?

Temos aqui o comentário Date d //Dia da semana

Sim mas e…? Você vai continuar sem entender a finalidade do código

Vamos imaginar outro exemplo:

Usuario usuario = new Usuario();

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

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

//….

}

Não seria melhor desse outro jeito

private static boolean isUsuarioTemDireitoAoBeneficio(Usuario usuario) {
return usuario.getIdade() > 10 && usuario.getIdade() < 20;
}

Veja que tiramos o comentário, melhoramos o código e ainda ficou mais fácil a leitura, mais legível, basta ler o código que você já consegue saber o ele irá fazer.

Ainda temos aqueles comentários totalmente inúteis, parece brincadeira, mas acontece

Tipo

return true//  retorna verdadeiro

Nesse caso o return é lógico não precisa dizer.

Você vai tentar colocar o seguinte na cabeça, se você fizer qualquer comentário que você precise olhar outras partes do código para entender então eles não tão valendo de nada.

Formatação

Imagine o seguinte código:

if (a > 1) {
if (b < 6) {
if (c < 9) {
}
}
}

Veja que bagunça, já está complicado pois está no estilo Date d, e ainda mais complicado pela indentação,

Agora veja como fica melhor de ler:

if (a > 1) {
if (b < 6) {
if (c < 9) {
}
}
}

E detalhe, uma boa pratica também não eh deixar essa escada toda

Evitar ifs e mais ifs dentro de ifs, por exemplo:

if (a > 1 && b > 5 && c > 1 && z > 1) {
//..
}

Um bom código deve está sempre bem formatado e indentado.

Refatoração

Escrever um bom código muitas vezes pode não parecer uma missão tão fácil, a gente tem a mania de olhar um código, digo por experiência, e de fazer o seguinte “Foi fulano que fez e não sou eu quem vai consertar.”.

É horrível propagar o erro dos outros. Vamos imaginar o seguinte código

private boolean isStringVazia(String texto) {
if (!StringUtils.isNullOrEmpty(texto) && !texto.equals(“”)) {
//…
}
}

Concordamos que o “!texto.equals(“”)” não serve para nada ? Pois é, se fizermos a refatoração abaixo vamos obter o mesmo resultado:

private boolean isStringVazia(String texto) {
return !StringUtils.isNullOrEmpty(texto);
}

A refatoração é uma das melhores práticas para você melhorar seu 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.

É gente com isso encerramos todo conteúdo abordado no vídeo.

Aprenda lógica de programação com Java: http://cursos.escolalinux.com.br/curso/logica-de-programacao-com-java-20-horas – Professor Edson Moretti.

Conheça outros cursos: http://cursos.escolalinux.com.br/

Um abraço a todos. Bons estudos.

Facebook - Comentários

Comentários