image

Bootcamps ilimitados + curso de inglês para sempre

80
%OFF
Article image
Edney Landim
Edney Landim27/01/2023 16:25
Compartilhe

Boas práticas em Java e a sua importância

    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.

    Fonte: Cod3r

    Compartilhe
    Recomendados para você
    Microsoft 50 Anos - Prompts Inteligentes
    Microsoft 50 Anos - GitHub Copilot
    Microsoft 50 Anos - Computação em Nuvem com Azure
    Comentários (4)
    Olival Neto
    Olival Neto - 27/01/2023 20:34

    Gostei do tema. Parabéns, Edney.

    PA

    Pedro Antunes - 27/01/2023 20:21

    Ótimas observações neste artigo.

    Membro Anônimo
    Membro Anônimo - 27/01/2023 16:43

    Ótimo artigo, sempre importante se atentar às boas práticas. Código funcionando não é o suficiente.

    Willian Farias
    Willian Farias - 27/01/2023 16:32

    Tema muito relevante