Fala, pessoal! Muitos programadores iniciantes tem dificuldades quanto às tão famosas “boas práticas” ou as práticas chamadas de “convenção”. O que é isso? Por que você precisar conhecer e fazer o uso adequado? Hoje eu vou esclarecer algumas das dúvidas nesse artigo, que tem como foco explicar as boas práticas em Java para quem está começando.
Boas Práticas vs Convenção
As boas práticas de desenvolvimento em Java, se referem a qualidade do código, com a intenção de deixá-lo mais otimizado, de mais fácil leitura e melhor organizado.
Já a convenção, significa literalmente um “acordo sobre determinada atividade, assunto, etc.”. Portanto, a convenção de determinada atividade no Java é um “acordo” da comunidade.
Certo, mas pra que isso serve afinal?
A finalidade dessa convenção é criar um “padrão” que faça com que organizemos o código da mesma forma aqui no Brasil ou em qualquer lugar do mundo.
Maus Hábitos de Iniciantes
No começo, todo mundo já teve dificuldade de entender o porquê da estrutura de um código ou de suas nomenclaturas.
Mas tenha em mente que existe um significado para tudo isso. Portanto, fazer diferente pode não ser “errado”, mas quebra o padrão utilizado pela comunidade.
O que também implica que por não ser errado, não é necessariamente correto. Ficou confuso? Relaxa! Vamos ver mais detalhes para entender melhor.
Existem inúmeras maneiras de organizar seu código. E nem sempre você fazer algo do seu jeito é errado.
Vou mostrar um exemplo a seguir:
public class Teste {
public static void main(String[] args) {
int somaDeDoisValores = 0;
somaDeDoisValores = 2 + 2;
int a=2+2;
}
}
Essas duas variáveis estão fazendo literalmente a mesma coisa.
Uma está de uma forma mais legível e a outra está de uma forma totalmente “comprimida”, mas as duas desempenham o mesmo papel. No entanto, suas organizações são completamente diferentes.
Ok, mas qual é o problema disso? De fato não há nenhum erro. Porém, as duas não estão seguindo boas práticas. Vou te explicar o por quê.
No primeiro exemplo, ela foi criada e iniciada antes de ser usada. Já no segundo exemplo, ela não tem uma convenção de nome adequado (detalhe: ela está totalmente “esmagada” sem espaços, e isso a torna um pouco menos legível. Isso deve ser considerado ao criar as variáveis).
Inicialização redundante
Mas e a inicialização redundante, o que é? É o ato você criar e iniciar as variáveis sem precisar delas.
No exemplo abaixo podemos perceber como isso funciona. Foram criadas três variáveis, e nenhuma delas é usada até a chamada do scanner. Isso, portanto, é uma má pratica que chamamos de inicialização redundante.
public class Teste {
public static void main(String[] args) {
String nome = "";
String sobrenome = "";
int idade=0;
Scanner scanner = new Scanner(System.in);
System.out.println("Digite seu nome: ");
nome = scanner.nextLine();
System.out.println("Digite seu sobrenome: ");
sobrenome = scanner.nextLine();
System.out.println("Digite sua idade: ");
idade = scanner.nextInt();
}
}
A maneira correta de se fazer as inicializações é criando a variável no mesmo momento que for utilizá-las.
Veja o exemplo a seguir:
public class Teste {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("Digite seu nome: ");
String nome = scanner.nextLine();
System.out.println("Digite seu sobrenome: ");
String sobrenome = scanner.nextLine();
System.out.println("Digite sua idade: ");
int idade = scanner.nextInt();
}
}
Aqui, o código continua funcionando perfeitamente, se tornou menor, com uma leitura mais simples, mais organizado, e ainda está menos propenso a bugs.
Formatação do Código (Identação)
As IDE’s possuem uma formatação automática do código a qual chamamos de identação. Essa formatação por si só faz diversas coisas praticamente imperceptíveis.
Antes de abrir escopos com chaves “ { “ ela sempre deixa um espaço, por exemplo, ou quando há uma operação, ela também deixa espaços. Portanto, isso a=2+2;
se transformaria nisso a = 2 + 2;
por questões de organização e legibilidade.
São coisas tão simples que você pode se perguntar, mas isso faz diferença mesmo? E a resposta é: com toda certeza!
Como é uma convenção da comunidade deixar esses espaços e outros detalhes, quando alguém ler um código que não está seguindo todas essas “regras” essa diferença será notada.
Nesse caso, existem duas opções: a pessoa pode imaginar que o programador que fez isso não é tão experiente a ponto de ter o conhecimento, ou não se interessa por isso. E isso, pra quem está entrando na área, querendo entrar ou até mesmo tentando ser promovido, pode ser prejudicial.
Também há a questão de “lugares” onde há possibilidades de abrir escopos em lugares indevidos. Por convenção, sempre abrimos na mesma linha que a declaração de determinada funcionalidade como if/else e métodos, como no exemplo abaixo:
public class Teste {
public static void main(String[] args) {
if (true) {
System.out.println("Mandou bem com essa abertura de escopo!");
}
----------------------------------------------------------------------------------
if (true)
{
System.out.println("Mandou bem!");
}
----------------------------------------------------------------------------------
if (true)
{System.out.println("Mandou muito mal agora!");}
}
}
Portanto…
Nos três exemplos acima, todos vão funcionar normalmente.
Mas se você tem um costume com Java, os exemplos dois e três com certeza vão soar um pouco estranho pra você, porque geralmente usamos a opção número um. No entanto, apesar de não usarmos no dia a dia o exemplo dois, não se trata de uma má prática, e, finalmente no exemplo três é uma má prática e não é aconselhável usar.
Entretanto a boa noticia é que as IDE’s hoje em dia fazem isso pra você, basta usar o atalho e ela formata quase tudo, e, mesmo nos casos extremos em que a formatação não é inteira, a maior parte do código será formatada.
Caso você não saiba qual é o atalho utilizado para formatar sua IDE, faça uma pesquisa no Google. Com certeza em menos de 1 minuto você consegue achar o atalho.
Faça o teste de pesquisar pelo seguinte termo “atalho de formatação de código no eclipse”. A primeira resposta será a sua solução.
Se for em um ambiente diferente do “padrão” Windows, é só adicionar o seu sistema operacional, e com certeza será da mesma forma.
Nomes de Variáveis e Métodos
Existem muitas convenções de nomenclaturas. Mas como nesse artigo eu vou falar apenas de algumas, vou deixar o link aqui abaixo para as convenções de nomes da própria documentação da Oracle:
https://www.oracle.com/java/technologies/javase/codeconventions-namingconventions.html
O primeiro tópico será o camelCase. Elas são palavras compostas sem espaços, como por exemplo: estouUsandoCamelCaseAgora.
Pode parecer estranho no primeiro contato, mas é assim que criamos nomes de variáveis, métodos e classes.
E lembre-se, quando formos nos referenciar a algo criado, devemos ter esse mesmo cuidado, porque Java é Case-sensitive. Isso significa que letras maiúscula e minúsculas são tratadas de formas diferentes, logo, uma variável com o nome de testeVariavel
não será reconhecida se tentar acessar por testevariavel
.
Mais um detalhe é que, variáveis e métodos devem conter suas iniciais minúsculas, e depois seguir o padrão camelCase. Diferente de Interfaces e Classes que devem ser criadas com seu nome iniciando com letra maiúscula.
Padrões de nomenclatura
Outro tópico extremamente importante e que muitas vezes é ignorado, são os significados dos nomes. Eles seriam nomes intuitivos, para que qualquer um que leia o nome da variável e método, consiga imaginar ou entender qual seu papel.
Isso pode até parecer muito simples e fácil, mas não é.
Então, sempre coloque nomes que mostrem o que aquilo significa ou faz. Não importa se ficar grande (obviamente, sem exagero) mas você pode, por exemplo, em um método que soma dois números, colocar o nome de somar()
. Não está errado, mas se você trabalhar com muitos métodos de cálculos, você pode ter somarDoisNumeros()
e somarTresNumeros()
e com isso se livrar daquelas variáveis e métodos com nomes de a
ou teste
. Quem nunca, né?
Outro ponto importante é aplicar uma padronização nos nomes dos métodos.
É aconselhável e de bom tom, usar os nomes no infinitivo e não no gerúndio na declaração de métodos, como por exemplo: pegarProdutos();, alterarProduto();, excluirProduto();
e não pegandoProduto();, alterandoProduto(); e excluindoProduto();
.
Ah, e muita atenção para não misturar criar um método excluindoProduto();
e outro alterarProduto();
nesse caso, ficará ainda mais desorganizado.
Não repita código
Existe um conceito extremamente importante na programação chamado DRY (Don’t repeat yourself ou “Não se repita”). Ele nada mais é do que, não repita código.
Pode não parecer, mas muitas pessoas desenvolvedoras não seguem esse conceito a risca, o que faz com que perguntemos: será que isso é realmente “fácil” de botar em prática?
Bem, não é tão simples assim, principalmente para estudantes. Em alguns momentos, não é tão “visível” a oportunidade de não repetir determinado código.
Mas como eu faço para não repetir código? É simples, principalmente por meio de métodos.
Também podemos reaproveitar códigos através da herança (com algumas limitações e consequências), e também pelo famoso CTRL + C
e CTRL + V
, que definitivamente é uma péssima escolha.
Então, o nosso herói pra reutilização de código são os métodos. Vamos ver alguns exemplos?
public class Teste {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("Digite a primeira nota do aluno: ");
Double nota1 = scanner.nextDouble();
if (nota1 < 0) {
throw new Exception("O número não pode ser negativo.");
} else if (nota1 > 10) {
throw new Exception("O número não pode ser maior que 10");
}
System.out.println("Digite a segunda nota do aluno: ");
Double nota2 = scanner.nextDouble();
if (nota2 < 0) {
throw new Exception("O número não pode ser negativo.");
} else if (nota2 > 10) {
throw new Exception("O número não pode ser maior que 10");
}
System.out.println("Digite a terceira nota do aluno: ");
Double nota3 = scanner.nextDouble();
if (nota3 < 0) {
throw new Exception("O número não pode ser negativo.");
} else if (nota3 > 10) {
throw new Exception("O número não pode ser maior que 10");
}
Double media = (nota1 + nota2 + nota3) / 3;
System.out.println(media);
}
}
Note a quantidade de vezes que repetimos o if/else, que estão aí apenas para fazer uma validação simples, mas tornam o código bem grande por algo tão fácil e simples de resolver. O if/else verifica apenas se um número está entre 0 e 10 e lança exceção caso não esteja.
Agora vamos dar uma melhorada nesse código:
public class Teste {
public static void main(String[] args) throws Exception {
Scanner scanner = new Scanner(System.in);
System.out.println("Digite a primeira nota do aluno: ");
Double nota1 = scanner.nextDouble();
verificarNumeroValido(nota1);
System.out.println("Digite a segunda nota do aluno: ");
Double nota2 = scanner.nextDouble();
verificarNumeroValido(nota2);
System.out.println("Digite a terceira nota do aluno: ");
Double nota3 = scanner.nextDouble();
verificarNumeroValido(nota3);
Double media = (nota1 + nota2 + nota3) / 3;
System.out.println(media);
}
static void verificarNumeroValido(Double num) throws Exception {
if (num < 0) {
throw new Exception("O número não pode ser negativo.");
} else if (num > 10) {
throw new Exception("O número não pode ser maior que 10");
}
}
}
Note que agora eu fiz um método para executar essa verificação, e no momento em que for necessário fazer a verificação eu chamarei esse método passando o número que eu quero que ele verifique.
Nós fizemos uma refatoração e ficou melhor, certo? Mas dá pra melhorar ainda mais! Vamos lá:
public class Teste {
public static void main(String[] args) throws Exception {
Scanner scanner = new Scanner(System.in);
System.out.println("Digite quantas notas irá cadastrar: ");
int qtdNotas = scanner.nextInt();
ArrayList<Double> notas = new ArrayList();
for (int i = 0; i < qtdNotas; i++) {
System.out.println("Digite a " + (i + 1) + "° nota: ");
notas.add(scanner.nextDouble());
verificarNumeroValido(notas.get(i));
}
double soma = 0;
for (int i = 0; i < notas.size(); i++) {
soma += notas.get(i);
}
Double media = soma / qtdNotas;
System.out.println(media);
}
static void verificarNumeroValido(Double num) throws Exception {
if (num < 0) {
throw new Exception("O número não pode ser negativo.");
} else if (num > 10) {
throw new Exception("O número não pode ser maior que 10");
}
}
}
Perceba que agora nós temos mais recursos à nossa disposição como controle da quantidade de alunos, sem ter que ficar repetindo linhas para solicitar mais uma nota. Isso tudo é feito a partir de laços e métodos. Achou interessante?
Bônus Importante!
Não tenha medo de pesquisar, isso é extremamente importante! Não consegue fazer algo, não consegue corrigir algo? Pesquise!
Na programação, muita coisa que se faz é sabendo pesquisar! Isso acontece em todas as linguagens, é algo que se torna hábito depois de um tempo, e você nem vai perceber.
Não conseguiu baixar algo ou configurar algo? Pesquise.
A comunidade de programadores é muita ativa e com certeza alguém já passou pelo que você está passando, então, você vai ter alguma solução ou no mínimo, alguma coisa semelhante que você vai poder se basear nisso.
E caso não ache, pesquise em inglês. Suas chances aumentam drasticamente.
Ah, e não precisa saber inglês. Use o Google tradutor para fazer a pergunta, e depois traduza as respostas que encontrar. Assim você aprende muita coisa!
Então, eu sugiro fortemente que, antes de você procurar a ajuda de alguém, tente você mesmo! Portanto, leia e releia perguntas e respostas que já resolveram seu problema, pegue a mensagem de seu bug e bote no Google, leia artigos e veja vídeos.
Espero que vocês tenham gostado das dicas e se você quiser estudar um pouco mais sobre o assunto, confere esse material que já produzimos:
Escrever código com ortografia correta usando Code Spell Checker
Um grande abraço e até a próxima!