image

Accede a bootcamps ilimitados y a más de 650 cursos para siempre

60
%OFF
Article image
Júlio Siqueira
Júlio Siqueira14/10/2025 19:21
Compartir

Aprenda a escrever código limpo e profissional com Java

  • #Java

Introdução

Quando começamos a programar em Java, é natural focar em fazer o código funcionar. No entanto, escrever código que apenas funciona não é suficiente no mundo profissional. A qualidade do código que produzimos tem um impacto direto na manutenibilidade, escalabilidade e sucesso dos projetos de software.

As boas práticas de programação em Java não são regras arbitrárias, mas sim lições aprendidas ao longo de décadas de desenvolvimento de software. Segundo Robert C. Martin, autor do clássico "Clean Code", código limpo é aquele que pode ser lido e melhorado por outros desenvolvedores com facilidade.

Este artigo tem como objetivo apresentar as principais boas práticas de Java que todo desenvolvedor iniciante deve conhecer e aplicar desde o começo de sua jornada. Abordaremos desde conceitos básicos como nomenclatura até aspectos mais avançados como organização de classes e estruturação de projetos.

Ao dominar essas práticas desde cedo, você não apenas se tornará um programador mais eficiente, mas também estará preparado para trabalhar em equipes profissionais e contribuir para projetos de grande escala. Vamos explorar cada conceito com exemplos práticos de código "antes e depois" para ilustrar o impacto dessas boas práticas.

image

1. Nomes Significativos em Java: A Base do Código Claro

A escolha de nomes apropriados para variáveis, métodos e classes é uma das práticas mais importantes e, paradoxalmente, uma das mais negligenciadas por iniciantes. Um bom nome deve revelar a intenção do código sem necessidade de comentários explicativos.

Princípios para Nomenclatura de Variáveis em Java

Ao nomear variáveis em Java, devemos seguir alguns princípios fundamentais que tornam o código autoexplicativo:

  • Use nomes pronunciáveis: Evite abreviações enigmáticas como "dtNsc" e prefira "dataNascimento"
  • Seja específico: Em vez de "lista" ou "dados", use "listaClientes" ou "dadosUsuario"
  • Evite prefixos desnecessários: Não use "strNome" ou "intIdade", o tipo já está declarado
  • Use convenções Java: Variáveis em camelCase, classes em PascalCase, constantes em UPPER_SNAKE_CASE
  • Nomes de booleanos: Devem soar como perguntas: "isValid", "hasPermission", "canExecute"

image

Nomenclatura de Métodos em Java: Verbos de Ação

Métodos representam ações, portanto seus nomes devem começar com verbos que descrevem claramente o que fazem. Segundo Joshua Bloch em "Effective Java", nomes de métodos devem ser concisos mas descritivos o suficiente para eliminar ambiguidades.

image

2. Organização de Classes em Java: Estrutura e Coesão

Uma classe bem organizada em Java segue uma estrutura consistente que facilita a leitura e manutenção. A organização adequada das classes é um dos pilares da programação orientada a objetos e reflete diretamente na qualidade do software produzido.

Ordem dos Elementos em uma Classe Java

A convenção Java estabelece uma ordem específica para os elementos de uma classe, promovendo consistência em todo o código:

  1. Constantes estáticas: Declaradas como public static final no topo da classe
  2. Variáveis estáticas: Campos estáticos privados ou protegidos
  3. Variáveis de instância: Atributos privados da classe
  4. Construtores: Do mais simples ao mais complexo
  5. Métodos públicos: A interface principal da classe
  6. Métodos privados: Implementações auxiliares

Exemplo de classe Bem organizada

public class ContaBancaria {
  // Constantes
  public static final double TAXA_JUROS = 0.05;
  private static final int DIGITOS_CONTA = 8;
  
  // Variáveis estáticas
  private static int contadorContas = 0;
  
  // Variáveis de instância
  private String numeroConta;
  private String titular;
  private double saldo;
  private boolean ativa;
  
  // Construtor
  public ContaBancaria(String titular, double saldoInicial) {
      this.titular = titular;
      this.saldo = saldoInicial;
      this.numeroConta = gerarNumeroConta();
      this.ativa = true;
      contadorContas++;
  }
  
  // Métodos públicos
  public void depositar(double valor) {
      if (validarValor(valor)) {
          this.saldo += valor;
      }
  }
  
  public boolean sacar(double valor) {
      if (validarSaque(valor)) {
          this.saldo -= valor;
          return true;
      }
      return false;
  }
  
  // Métodos privados
  private boolean validarValor(double valor) {
      return valor > 0;
  }
  
  private boolean validarSaque(double valor) {
      return validarValor(valor) && valor <= saldo;
  }
  
  private String gerarNumeroConta() {
      return String.format("%08d", contadorContas + 1);
  }
}

Princípio da Responsabilidade Única em Java

O princípio SOLID de Responsabilidade Única (Single Responsibility Principle) estabelece que uma classe deve ter apenas uma razão para mudar. Isso significa que cada classe deve ter uma única responsabilidade bem definida no sistema.

Classe com Múltipla responsabiidade

public class Usuario {
  private String nome;
  private String email;
  
  // Validação
  public boolean validarEmail() {
      return email.contains("@");
  }
  
  // Persistência
  public void salvarNoBancoDados() {
      // código SQL
  }
  
  // Envio de email
  public void enviarEmailBoasVindas() {
      // código de envio
  }
  
  // Geração de relatório
  public String gerarRelatorio() {
      return "Relatório do usuário";
  }
}

Classes com Responsabiidades Separadas

public class Usuario {
  private String nome;
  private String email;
  
  // Getters e setters apenas
}

public class ValidadorEmail {
  public boolean validar(String email) {
      return email != null && email.contains("@");
  }
}

public class UsuarioRepository {
  public void salvar(Usuario usuario) {
      // código de persistência
  }
}

public class EmailService {
  public void enviarBoasVindas(Usuario usuario) {
      // código de envio
  }
}

3. Comentários Úteis em Java: Quando e Como Comentar

Existe um equívoco comum entre iniciantes de que código bem comentado é sinônimo de código de qualidade. Na verdade, como afirma Martin Fowler, "o código deve ser autoexplicativo, e os comentários devem explicar o porquê, não o quê". Comentários excessivos ou inadequados podem se tornar um problema de manutenção.

Quando NÃO Comentar em Java

  • Código óbvio: Não comente operações simples como "// incrementa contador"
  • Código ruim: Em vez de comentar código confuso, refatore-o para ser claro
  • Informações redundantes: Não repita o que o nome da função já diz
  • Histórico de alterações: Use controle de versão (Git) em vez de comentários
  • Código comentado: Delete código não utilizado em vez de apenas comentá-lo

image

Quando Comentários São Necessários em Java

Existem situações específicas onde comentários são não apenas úteis, mas essenciais para a compreensão do código. Nesses casos, os comentários agregam valor real ao explicar decisões de design, complexidades algorítmicas ou avisos importantes.

Exemplos de Comentários Úteis

public class ProcessadorPagamento {
  /**
   * Processa pagamento com retry exponencial.
   * 
   * @param pagamento Objeto com dados do pagamento
   * @return true se processado com sucesso
   * @throws PagamentoException se falhar após 3 tentativas
   * 
   * IMPORTANTE: Este método implementa circuit breaker para
   * evitar sobrecarga no gateway de pagamento. Não remover
   * a lógica de retry sem consultar a equipe de infraestrutura.
   */
  public boolean processar(Pagamento pagamento) {
      // Usamos SHA-256 em vez de MD5 por requisitos de segurança PCI-DSS
      String hash = gerarHashSHA256(pagamento);
      
      // TODO: Implementar notificação por webhook quando o
      // gateway de pagamento atualizar sua API v3 (previsto Q2 2025)
      
      return enviarParaGateway(hash, pagamento);
  }
  
  /**
   * Algoritmo de Luhn para validação de cartão.
   * Complexidade: O(n) onde n é número de dígitos
   */
  private boolean validarNumeroCartao(String numero) {
      // Implementação do algoritmo de Luhn
      int soma = 0;
      boolean alternado = false;
      
      for (int i = numero.length() - 1; i >= 0; i--) {
          int digito = Character.getNumericValue(numero.charAt(i));
          
          if (alternado) {
              digito *= 2;
              if (digito > 9) {
                  digito -= 9;
              }
          }
          
          soma += digito;
          alternado = !alternado;
      }
      
      return soma % 10 == 0;
  }
}

4. Formatação Consistente em Java: A Importância da Legibilidade

A formatação consistente do código não é uma questão de preferência pessoal, mas sim uma necessidade profissional. Segundo pesquisa da Oracle, desenvolvedores gastam aproximadamente 70% do tempo lendo código e apenas 30% escrevendo. Portanto, a legibilidade é fundamental para a produtividade da equipe.

Convenções de Formatação Java Standard

  • Indentação: Use 4 espaços (ou 1 tab configurado para 4 espaços) para cada nível
  • Chaves: Abra na mesma linha (estilo K&R) e feche em linha própria alinhada
  • Linhas em branco: Use uma linha entre métodos, duas entre classes no mesmo arquivo
  • Comprimento da linha: Limite a 80-120 caracteres por linha
  • Espaçamento: Use espaços ao redor de operadores: a + b, não a+b
  • Imports: Organize em grupos: java.*, javax.*, org.*, com.*, depois classes do projeto

Exemplos de formatação:

Formatação Inconsistente

import java.util.*;import java.io.*;
public class exemplo{
private String nome;private int idade;
public void metodo1(){
if(idade>18){
System.out.println("Adulto");}
else{System.out.println("Menor");}}
public boolean validar(String s){return s!=null&&s.length()>0;}
}

Formatação Consistente

import java.io.*;
import java.util.*;

public class Exemplo {
  private String nome;
  private int idade;
  
  public void classificarIdade() {
      if (idade > 18) {
          System.out.println("Adulto");
      } else {
          System.out.println("Menor");
      }
  }
  
  public boolean validarString(String texto) {
      return texto != null && texto.length() > 0;
  }
}

Ferramentas de Formatação Automática para Java

Em vez de formatar manualmente, utilize ferramentas que garantem consistência automática. As principais IDEs Java oferecem formatadores integrados que seguem as convenções da linguagem.

Ferramentas Recomendadas:

  • Google Java Format: Formatador oficial do Google, impõe estilo consistente
  • IntelliJ IDEA Formatter: Altamente configurável, integrado à IDE
  • Eclipse Formatter: Padrão da Eclipse Foundation, amplamente usado
  • Checkstyle: Verifica conformidade com padrões de código Java
  • SpotlessApply: Plugin Gradle/Maven para formatação em builds

5. Tratamento de Exceções em Java: Robustez e Confiabilidade

O tratamento adequado de exceções é crucial para criar aplicações Java robustas e confiáveis. Segundo Joshua Bloch em "Effective Java", exceções devem ser usadas apenas para condições excepcionais, não para controle de fluxo normal do programa.

Princípios de Tratamento de Exceções em Java

  • Seja específico: Capture exceções específicas, não apenas Exception
  • Não silencie exceções: Nunca deixe blocos catch vazios
  • Falhe rápido: Valide parâmetros no início e lance exceções imediatamente
  • Mensagens descritivas: Forneça contexto útil nas mensagens de erro
  • Try-with-resources: Use para recursos que precisam ser fechados

Tratamento Inadequado de Exceções

public class ArquivoService {
  public String lerArquivo(String caminho) {
      try {
          FileReader reader = new FileReader(caminho);
          BufferedReader buffer = new BufferedReader(reader);
          String conteudo = buffer.readLine();
          return conteudo;
      } catch (Exception e) {
          // Silenciando a exceção
          return null;
      }
  }
  
  public void processar(String dados) throws Exception {
      // Lançando Exception genérica
      if (dados == null) {
          throw new Exception("Erro");
      }
  }
}

Tratamento Adequado de Exceções

public class ArquivoService {
  public String lerArquivo(String caminho) 
          throws ArquivoNaoEncontradoException, 
                 ErroLeituraException {
      try (FileReader reader = new FileReader(caminho);
           BufferedReader buffer = new BufferedReader(reader)) {
          
          String conteudo = buffer.readLine();
          if (conteudo == null) {
              throw new ErroLeituraException(
                  "Arquivo vazio: " + caminho
              );
          }
          return conteudo;
          
      } catch (FileNotFoundException e) {
          throw new ArquivoNaoEncontradoException(
              "Arquivo não encontrado: " + caminho, e
          );
      } catch (IOException e) {
          throw new ErroLeituraException(
              "Erro ao ler arquivo: " + caminho, e
          );
      }
  }
  
  public void processar(String dados) {
      Objects.requireNonNull(dados, 
          "Parâmetro dados não pode ser nulo"
      );
  }
}

6. Testes em Java: Garantindo Qualidade desde o Início

Escrever testes não é opcional no desenvolvimento profissional de software. Testes automatizados são a rede de segurança que permite refatorar e evoluir o código com confiança. Segundo Kent Beck, criador do JUnit, "não é sobre testar, é sobre confiança".

Boas Práticas de Testes Unitários em Java

  • Padrão AAA: Organize testes em Arrange (preparar), Act (agir), Assert (verificar)
  • Um assert por teste: Cada teste deve verificar apenas uma coisa
  • Nomes descritivos: O nome do teste deve descrever o cenário e resultado esperado
  • Independência: Testes não devem depender uns dos outros
  • Rápidos: Testes unitários devem executar em milissegundos

Exemplo de teste unitário com JUnit 5

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.DisplayName;
import static org.junit.jupiter.api.Assertions.*;

@DisplayName("Testes da classe ContaBancaria")
class ContaBancariaTest {
  
  @Test
  @DisplayName("Deve depositar valor positivo com sucesso")
  void deveDepositarValorPositivo() {
      // Arrange - Preparação
      ContaBancaria conta = new ContaBancaria("João", 1000.0);
      double valorDeposito = 500.0;
      
      // Act - Ação
      conta.depositar(valorDeposito);
      
      // Assert - Verificação
      assertEquals(1500.0, conta.getSaldo(), 
          "Saldo deve ser 1500 após depósito de 500");
  }
  
  @Test
  @DisplayName("Deve rejeitar depósito de valor negativo")
  void deveRejeitarDepositoNegativo() {
      // Arrange
      ContaBancaria conta = new ContaBancaria("Maria", 1000.0);
      double saldoInicial = conta.getSaldo();
      
      // Act
      conta.depositar(-100.0);
      
      // Assert
      assertEquals(saldoInicial, conta.getSaldo(),
          "Saldo não deve mudar ao tentar depositar valor negativo");
  }
  
  @Test
  @DisplayName("Deve lançar exceção ao sacar valor maior que saldo")
  void deveLancarExcecaoAoSacarMaisQueSaldo() {
      // Arrange
      ContaBancaria conta = new ContaBancaria("Pedro", 100.0);
      
      // Act & Assert
      assertThrows(SaldoInsuficienteException.class, 
          () -> conta.sacar(200.0),
          "Deve lançar SaldoInsuficienteException");
  }
}

Conclusão

As boas práticas apresentadas neste artigo não são apenas recomendações teóricas, mas sim fundamentos essenciais que separam desenvolvedores iniciantes de profissionais competentes. Ao adotar essas práticas desde o início de sua jornada com Java, você estará construindo uma base sólida para sua carreira.

Lembre-se que código limpo não é sobre seguir regras rigidamente, mas sobre comunicação efetiva e respeito pela equipe. Como Martin Fowler sabiamente disse: "Qualquer tolo consegue escrever código que um computador entende. Bons programadores escrevem código que humanos entendem."

Referências Utilizadas

  • Martin, R. C. (2008). Clean Code: A Handbook of Agile Software Craftsmanship. Prentice Hall.
  • Bloch, J. (2018). Effective Java (3rd ed.). Addison-Wesley Professional.
  • Fowler, M. (2018). Refactoring: Improving the Design of Existing Code (2nd ed.). Addison-Wesley Professional.
  • Oracle. (2024). Java Code Conventions. Oracle Corporation.
  • Beck, K. (2002). Test Driven Development: By Example. Addison-Wesley Professional.
  • Martin, R. C. (2017). Clean Architecture: A Craftsman's Guide to Software Structure and Design. Prentice Hall.
  • Google. (2024). Google Java Style Guide. Google Inc.
Compartir
Recomendado para ti
PcD Tech Bradesco - Java & QA Developer
Riachuelo - Primeiros Passos com Java
GFT Start #7 - Java
Comentarios (1)
Iasmin Santiago
Iasmin Santiago - 14/10/2025 21:23

Esse artigo trouxe muitas dicas que me ajudarão bastante, agora e no futuro, a ser uma desenvolvedora melhor. Excelente! Obrigada por compartilhar esse conhecimento conosco :)