Estilo de código Java AOSP para contribuidores

Os estilos de código nesta página são regras estritas para contribuir com código Java para o Android Open Source Project (AOSP). As contribuições para a plataforma Android que não cumpram essas regras geralmente não são aceitas . Reconhecemos que nem todos os códigos existentes seguem estas regras, mas esperamos que todos os novos códigos sejam compatíveis. Consulte Codificação com respeito para exemplos de terminologia a usar e evitar para um ecossistema mais inclusivo.

Ser consistente

Uma das regras mais simples é SER CONSISTENTE. Se você estiver editando código, reserve alguns minutos para observar o código ao redor e determinar seu estilo. Se esse código usa espaços ao redor das cláusulas if , você também deveria. Se os comentários do código tiverem pequenas caixas de estrelas ao redor deles, faça com que seus comentários tenham pequenas caixas de estrelas ao redor deles também.

O objetivo de ter diretrizes de estilo é ter um vocabulário comum de codificação, para que os leitores possam se concentrar no que você está dizendo, e não em como você está dizendo. Apresentamos aqui regras de estilo globais para que você conheça o vocabulário, mas o estilo local também é importante. Se o código que você adiciona a um arquivo parecer drasticamente diferente do código existente em torno dele, isso tira o ritmo dos leitores ao lê-lo. Tente evitar isso.

Regras da linguagem Java

O Android segue as convenções de codificação Java padrão com as regras adicionais descritas abaixo.

Não ignore exceções

Pode ser tentador escrever código que ignore uma exceção, como:

  void setServerPort(String value) {
      try {
          serverPort = Integer.parseInt(value);
      } catch (NumberFormatException e) { }
  }

Não faça isso. Embora você possa pensar que seu código nunca encontrará essa condição de erro ou que não é importante lidar com ela, ignorar esse tipo de exceção cria minas em seu código para que outra pessoa acione algum dia. Você deve lidar com todas as exceções em seu código de maneira baseada em princípios; o manuseio específico varia dependendo do caso.

" Sempre que alguém tem uma cláusula catch vazia, ele deve ter uma sensação assustadora. Definitivamente, há momentos em que é realmente a coisa correta a fazer, mas pelo menos você tem que pensar sobre isso. Em Java você não pode escapar da sensação assustadora. " -James Gosling

Alternativas aceitáveis ​​(em ordem de preferência) são:

  • Lance a exceção para o chamador do seu método.
      void setServerPort(String value) throws NumberFormatException {
          serverPort = Integer.parseInt(value);
      }
    
  • Lance uma nova exceção apropriada ao seu nível de abstração.
      void setServerPort(String value) throws ConfigurationException {
        try {
            serverPort = Integer.parseInt(value);
        } catch (NumberFormatException e) {
            throw new ConfigurationException("Port " + value + " is not valid.");
        }
      }
    
  • Trate o erro normalmente e substitua um valor apropriado no bloco catch {} .
      /** Set port. If value is not a valid number, 80 is substituted. */
    
      void setServerPort(String value) {
        try {
            serverPort = Integer.parseInt(value);
        } catch (NumberFormatException e) {
            serverPort = 80;  // default port for server
        }
      }
    
  • Capture a exceção e lance uma nova instância de RuntimeException . Isso é perigoso, portanto, faça-o apenas se tiver certeza de que, se esse erro ocorrer, a coisa apropriada a fazer é travar.
      /** Set port. If value is not a valid number, die. */
    
      void setServerPort(String value) {
        try {
            serverPort = Integer.parseInt(value);
        } catch (NumberFormatException e) {
            throw new RuntimeException("port " + value " is invalid, ", e);
        }
      }
    
  • Como último recurso, se você tiver certeza de que ignorar a exceção é apropriado, poderá ignorá-la, mas também deverá comentar o motivo com um bom motivo.
    /** If value is not a valid number, original port number is used. */
    
    void setServerPort(String value) {
        try {
            serverPort = Integer.parseInt(value);
        } catch (NumberFormatException e) {
            // Method is documented to just ignore invalid user input.
            // serverPort will just be unchanged.
        }
    }
    

Não capture exceções genéricas

Pode ser tentador ser preguiçoso ao capturar exceções e fazer algo assim:

  try {
      someComplicatedIOFunction();        // may throw IOException
      someComplicatedParsingFunction();   // may throw ParsingException
      someComplicatedSecurityFunction();  // may throw SecurityException
      // phew, made it all the way
  } catch (Exception e) {                 // I'll just catch all exceptions
      handleError();                      // with one generic handler!
  }

Não faça isso. Em quase todos os casos, é inapropriado capturar Exception ou Throwable genéricos (de preferência não Throwable porque inclui exceções Error ). É perigoso porque significa que exceções que você nunca esperava (incluindo exceções de tempo de execução como ClassCastException ) são capturadas no tratamento de erros no nível do aplicativo. Ele obscurece as propriedades de tratamento de falhas do seu código, o que significa que se alguém adicionar um novo tipo de exceção no código que você está chamando, o compilador não apontará que você precisa tratar o erro de maneira diferente. Na maioria dos casos, você não deveria lidar com diferentes tipos de exceções da mesma maneira.

A rara exceção a esta regra é o código de teste e o código de nível superior onde você deseja capturar todos os tipos de erros (para evitar que eles apareçam em uma UI ou para manter um trabalho em lote em execução). Nesses casos, você pode capturar Exception genérica (ou Throwable ) e tratar o erro adequadamente. Pense bem antes de fazer isso e coloque comentários explicando por que é seguro neste contexto.

Alternativas para capturar exceções genéricas:

  • Capture cada exceção separadamente como parte de um bloco multi-catch, por exemplo:
    try {
        ...
    } catch (ClassNotFoundException | NoSuchMethodException e) {
        ...
    }
  • Refatore seu código para ter um tratamento de erros mais refinado, com vários blocos try. Separe o IO da análise e trate os erros separadamente em cada caso.
  • Relançar a exceção. Muitas vezes você não precisa capturar a exceção nesse nível, apenas deixe o método lançá-la.

Lembre-se de que as exceções são suas amigas! Quando o compilador reclamar que você não está capturando uma exceção, não faça cara feia. Sorriso! O compilador apenas tornou mais fácil detectar problemas de tempo de execução em seu código.

Não use finalizadores

Finalizadores são uma maneira de executar um pedaço de código quando um objeto é coletado como lixo. Embora os finalizadores possam ser úteis para limpeza (particularmente de recursos externos), não há garantias de quando um finalizador será chamado (ou mesmo de que ele será chamado).

O Android não usa finalizadores. Na maioria dos casos, você pode usar um bom tratamento de exceções. Se você realmente precisa de um finalizador, defina um método close() (ou algo semelhante) e documente exatamente quando esse método precisa ser chamado (veja InputStream para obter um exemplo). Nesse caso, é apropriado, mas não obrigatório, imprimir uma mensagem curta de log do finalizador, desde que não seja esperado que os logs sejam inundados.

Qualificar totalmente as importações

Quando você quiser usar a classe Bar do pacote foo , existem duas maneiras possíveis de importá-la:

  • import foo.*;

    Reduz potencialmente o número de instruções de importação.

  • import foo.Bar;

    Torna óbvio quais classes são usadas e o código é mais legível para os mantenedores.

Use import foo.Bar; para importar todo o código Android. Uma exceção explícita é feita para bibliotecas padrão Java ( java.util.* , java.io.* , etc.) e código de teste de unidade ( junit.framework.* ).

Regras da biblioteca Java

Existem convenções para usar as bibliotecas e ferramentas Java do Android. Em alguns casos, a convenção mudou de maneiras importantes e o código mais antigo pode usar um padrão ou biblioteca obsoleta. Ao trabalhar com esse código, não há problema em continuar com o estilo existente. Entretanto, ao criar novos componentes, nunca use bibliotecas obsoletas.

Regras de estilo Java

Use comentários padrão Javadoc

Cada arquivo deve ter uma declaração de copyright no topo, seguida pelas declarações package e import (cada bloco separado por uma linha em branco) e, finalmente, a declaração de classe ou interface. Nos comentários Javadoc, descreva o que a classe ou interface faz.

/*
 * Copyright 2024 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.internal.foo;

import android.os.Blah;
import android.view.Yada;

import java.sql.ResultSet;
import java.sql.SQLException;

/**
 * Does X and Y and provides an abstraction for Z.
 */

public class Foo {
    ...
}

Cada classe e método público não trivial que você escreve deve conter um comentário Javadoc com pelo menos uma frase descrevendo o que a classe ou método faz. Esta frase deve começar com um verbo descritivo de terceira pessoa.

Exemplos

/** Returns the correctly rounded positive square root of a double value. */

static double sqrt(double a) {
    ...
}

ou

/**
 * Constructs a new String by converting the specified array of
 * bytes using the platform's default character encoding.
 */
public String(byte[] bytes) {
    ...
}

Você não precisa escrever Javadoc para métodos get e set triviais, como setFoo() se todo o seu Javadoc disser for "sets Foo". Se o método fizer algo mais complexo (como impor uma restrição ou tiver um efeito colateral importante), você deverá documentá-lo. Se não for óbvio o que significa a propriedade "Foo", você deve documentá-la.

Cada método que você escreve, público ou não, se beneficiaria com o Javadoc. Os métodos públicos fazem parte de uma API e, portanto, requerem Javadoc. O Android não impõe um estilo específico para escrever comentários Javadoc, mas você deve seguir as instruções em Como escrever comentários de documentos para a ferramenta Javadoc .

Escreva métodos curtos

Quando viável, mantenha os métodos pequenos e focados. Reconhecemos que métodos longos às vezes são apropriados, portanto nenhum limite rígido é colocado no comprimento do método. Se um método exceder cerca de 40 linhas, pense se ele pode ser dividido sem prejudicar a estrutura do programa.

Defina campos em locais padrão

Defina os campos na parte superior do arquivo ou imediatamente antes dos métodos que os utilizam.

Limitar o escopo da variável

Mantenha o escopo das variáveis ​​locais ao mínimo. Isso aumenta a legibilidade e a manutenção do seu código e reduz a probabilidade de erro. Declare cada variável no bloco mais interno que inclui todos os usos da variável.

Declare variáveis ​​locais no ponto onde elas são usadas pela primeira vez. Quase toda declaração de variável local deve conter um inicializador. Se você ainda não possui informações suficientes para inicializar uma variável de maneira sensata, adie a declaração até fazê-lo.

A exceção são as instruções try-catch. Se uma variável for inicializada com o valor de retorno de um método que lança uma exceção verificada, ela deverá ser inicializada dentro de um bloco try. Se o valor deve ser usado fora do bloco try, então ele deve ser declarado antes do bloco try, onde ainda não pode ser inicializado de forma sensata:

// Instantiate class cl, which represents some sort of Set

Set s = null;
try {
    s = (Set) cl.newInstance();
} catch(IllegalAccessException e) {
    throw new IllegalArgumentException(cl + " not accessible");
} catch(InstantiationException e) {
    throw new IllegalArgumentException(cl + " not instantiable");
}

// Exercise the set
s.addAll(Arrays.asList(args));

No entanto, você pode até evitar esse caso encapsulando o bloco try-catch em um método:

Set createSet(Class cl) {
    // Instantiate class cl, which represents some sort of Set
    try {
        return (Set) cl.newInstance();
    } catch(IllegalAccessException e) {
        throw new IllegalArgumentException(cl + " not accessible");
    } catch(InstantiationException e) {
        throw new IllegalArgumentException(cl + " not instantiable");
    }
}

...

// Exercise the set
Set s = createSet(cl);
s.addAll(Arrays.asList(args));

Declare variáveis ​​de loop na própria instrução for, a menos que haja uma razão convincente para fazer o contrário:

for (int i = 0; i < n; i++) {
    doSomething(i);
}

e

for (Iterator i = c.iterator(); i.hasNext(); ) {
    doSomethingElse(i.next());
}

Solicitar extratos de importação

A ordem das instruções de importação é:

  1. Importações do Android
  2. Importações de terceiros ( com , junit , net , org )
  3. java e javax

Para corresponder exatamente às configurações do IDE, as importações devem ser:

  • Alfabético dentro de cada agrupamento, com letras maiúsculas antes de letras minúsculas (por exemplo, Z antes de a)
  • Separados por uma linha em branco entre cada agrupamento principal ( android , com , junit , net , org , java , javax )

Originalmente, não havia nenhum requisito de estilo na ordem, o que significa que os IDEs estavam sempre mudando a ordem ou os desenvolvedores de IDE tinham que desabilitar os recursos de gerenciamento automático de importação e manter manualmente as importações. Isso foi considerado ruim. Quando o estilo Java foi solicitado, os estilos preferidos variaram muito e o Android precisava simplesmente "escolher uma ordem e ser consistente". Então escolhemos um estilo, atualizamos o guia de estilo e fizemos com que os IDEs o obedecessem. Esperamos que, à medida que os usuários do IDE trabalhem no código, as importações em todos os pacotes correspondam a esse padrão sem esforço extra de engenharia.

Escolhemos este estilo tal que:

  • As importações que as pessoas querem ver primeiro tendem a estar no topo ( android ).
  • As importações que as pessoas querem pelo menos ver tendem a ficar na parte inferior ( java ).
  • Os humanos podem facilmente seguir o estilo.
  • IDEs podem seguir o estilo.

Coloque as importações estáticas acima de todas as outras importações ordenadas da mesma forma que as importações regulares.

Use espaços para recuo

Usamos quatro (4) recuos de espaço para blocos e nunca tabulações. Em caso de dúvida, seja consistente com o código circundante.

Usamos oito (8) recuos de espaço para quebras de linha, incluindo chamadas de função e atribuições.

Recomendado

Instrument i =
        someLongExpression(that, wouldNotFit, on, one, line);

Não recomendado

Instrument i =
    someLongExpression(that, wouldNotFit, on, one, line);

Siga as convenções de nomenclatura de campos

  • Nomes de campos não públicos e não estáticos começam com m .
  • Os nomes dos campos estáticos começam com s .
  • Outros campos começam com uma letra minúscula.
  • Os campos finais estáticos (constantes, profundamente imutáveis) são ALL_CAPS_WITH_UNDERSCORES .

Por exemplo:

public class MyClass {
    public static final int SOME_CONSTANT = 42;
    public int publicField;
    private static MyClass sSingleton;
    int mPackagePrivate;
    private int mPrivate;
    protected int mProtected;
}

Use estilo de chave padrão

Coloque colchetes na mesma linha do código anterior, não em sua própria linha:

class MyClass {
    int func() {
        if (something) {
            // ...
        } else if (somethingElse) {
            // ...
        } else {
            // ...
        }
    }
}

Exigimos colchetes em torno das instruções para uma condicional. Exceção: se toda a condicional (a condição e o corpo) couber em uma linha, você pode (mas não é obrigado a) colocar tudo em uma linha. Por exemplo, isso é aceitável:

if (condition) {
    body();
}

e isso é aceitável:

if (condition) body();

mas isso não é aceitável:

if (condition)
    body();  // bad!

Limitar comprimento da linha

Cada linha de texto do seu código deve ter no máximo 100 caracteres. Embora muita discussão tenha rodeado esta regra, permanece a decisão de que 100 caracteres é o máximo , com as seguintes exceções :

  • Se uma linha de comentário contiver um comando de exemplo ou um URL literal com mais de 100 caracteres, essa linha poderá ter mais de 100 caracteres para facilitar o corte e a colagem.
  • As linhas de importação podem ultrapassar o limite porque os humanos raramente as veem (isso também simplifica a escrita de ferramentas).

Use anotações Java padrão

As anotações devem preceder outros modificadores para o mesmo elemento de linguagem. Anotações de marcadores simples (por exemplo, @Override ) podem ser listadas na mesma linha do elemento de idioma. Se houver várias anotações ou anotações parametrizadas, liste-as uma por linha em ordem alfabética.

As práticas padrão do Android para as três anotações predefinidas em Java são:

  • Use a anotação @Deprecated sempre que o uso do elemento anotado for desencorajado. Se você usar a anotação @Deprecated , também deverá ter uma tag Javadoc @deprecated e ela deverá nomear uma implementação alternativa. Além disso, lembre-se de que um método @Deprecated ainda deve funcionar . Se você vir um código antigo que possui uma tag Javadoc @deprecated , adicione a anotação @Deprecated .
  • Use a anotação @Override sempre que um método substituir a declaração ou implementação de uma superclasse. Por exemplo, se você usar a tag Javadoc @inheritdocs e derivar de uma classe (não de uma interface), também deverá anotar que o método substitui o método da classe pai.
  • Use a anotação @SuppressWarnings somente em circunstâncias em que seja impossível eliminar um aviso. Se um aviso passar neste teste "impossível de eliminar", a anotação @SuppressWarnings deverá ser usada para garantir que todos os avisos reflitam problemas reais no código.

    Quando uma anotação @SuppressWarnings for necessária, ela deverá ser prefixada com um comentário TODO que explique a condição "impossível de eliminar". Isso normalmente identifica uma classe ofensiva que possui uma interface estranha. Por exemplo:

    // TODO: The third-party class com.third.useful.Utility.rotate() needs generics
    @SuppressWarnings("generic-cast")
    List<String> blix = Utility.rotate(blax);
    

    Quando uma anotação @SuppressWarnings for necessária, refatore o código para isolar os elementos de software aos quais a anotação se aplica.

Trate siglas como palavras

Trate acrônimos e abreviações como palavras ao nomear variáveis, métodos e classes para tornar os nomes mais legíveis:

Bom Ruim
XmlHttpRequest Solicitação XMLHTTP
getCustomerId obterIDDoCliente
classeHtml classeHTML
URL da string URL da string
ID longo ID longo

Como as bases de código JDK e Android são inconsistentes em relação aos acrônimos, é virtualmente impossível ser consistente com o código circundante. Portanto, trate sempre as siglas como palavras.

Use comentários TODO

Use comentários TODO para código temporário, uma solução de curto prazo ou bom o suficiente, mas não perfeito. Esses comentários devem incluir a string TODO em letras maiúsculas, seguida de dois pontos:

// TODO: Remove this code after the UrlTable2 has been checked in.

e

// TODO: Change this to use a flag instead of a constant.

Se o seu TODO estiver no formato "Em uma data futura, faça alguma coisa", certifique-se de incluir uma data específica ("Corrigir até novembro de 2005") ou um evento específico ("Remova este código depois que todos os mixers de produção entenderem o protocolo V7." ).

Registre com moderação

Embora o registro seja necessário, ele tem um impacto negativo no desempenho e perde sua utilidade se não for mantido de forma razoavelmente concisa. Os recursos de registro fornecem cinco níveis diferentes de registro:

  • ERROR : Use quando algo fatal acontecer, ou seja, algo terá consequências visíveis ao usuário e não será recuperável sem excluir alguns dados, desinstalar aplicativos, limpar as partições de dados ou atualizar todo o dispositivo (ou pior). Este nível é sempre registrado. Problemas que justificam algum registro no nível ERROR são bons candidatos para serem relatados a um servidor de coleta de estatísticas.
  • WARNING : Use quando algo sério e inesperado acontecer, ou seja, algo que terá consequências visíveis ao usuário, mas que provavelmente será recuperável sem perda de dados, executando alguma ação explícita, desde esperar ou reiniciar um aplicativo até baixá-lo novamente uma nova versão de um aplicativo ou reiniciando o dispositivo. Este nível é sempre registrado. As questões que justificam o registo no nível WARNING também podem ser consideradas para reportar a um servidor de recolha de estatísticas.
  • INFORMATIVE : Use para observar que algo interessante aconteceu, ou seja, quando é detectada uma situação que provavelmente terá um impacto generalizado, embora não seja necessariamente um erro. Tal condição só deve ser registrada por um módulo que acredita ser o mais autoritativo naquele domínio (para evitar registro duplicado por componentes não autoritativos). Este nível é sempre registrado.
  • DEBUG : Use para observar melhor o que está acontecendo no dispositivo que pode ser relevante para investigar e depurar comportamentos inesperados. Registre apenas o que for necessário para coletar informações suficientes sobre o que está acontecendo com seu componente. Se seus logs de depuração estiverem dominando o log, você deverá usar o log detalhado.

    Este nível é registrado mesmo em compilações de versão e deve ser cercado por um bloco if (LOCAL_LOG) ou if LOCAL_LOGD) , onde LOCAL_LOG[D] é definido em sua classe ou subcomponente, para que haja a possibilidade de desabilitar todos esses registros. . Portanto, não deve haver nenhuma lógica ativa em um bloco if (LOCAL_LOG) . Toda a construção de strings para o log também precisa ser colocada dentro do bloco if (LOCAL_LOG) . Não refatore a chamada de registro em uma chamada de método se isso fizer com que a construção da string ocorra fora do bloco if (LOCAL_LOG) .

    Há algum código que ainda diz if (localLOGV) . Isto também é considerado aceitável, embora o nome não seja padrão.

  • VERBOSE : Use para todo o resto. Este nível só é registrado em compilações de depuração e deve ser cercado por um bloco if (LOCAL_LOGV) (ou equivalente) para que possa ser compilado por padrão. Qualquer construção de string é removida das compilações de lançamento e precisa aparecer dentro do bloco if (LOCAL_LOGV) .

Notas

  • Dentro de um determinado módulo, exceto no nível VERBOSE , um erro só deverá ser relatado uma vez, se possível. Dentro de uma única cadeia de chamadas de função dentro de um módulo, apenas a função mais interna deve retornar o erro, e os chamadores no mesmo módulo só devem adicionar algum registro se isso ajudar significativamente a isolar o problema.
  • Em uma cadeia de módulos, exceto no nível VERBOSE , quando um módulo de nível inferior detecta dados inválidos provenientes de um módulo de nível superior, o módulo de nível inferior deve apenas registrar esta situação no log DEBUG , e somente se o registro fornecer informações que de outra forma não estão disponíveis para o chamador. Especificamente, não há necessidade de registrar situações em que uma exceção é lançada (a exceção deve conter todas as informações relevantes) ou em que a única informação registrada está contida em um código de erro. Isto é especialmente importante na interação entre a estrutura e os aplicativos, e as condições causadas por aplicativos de terceiros que são tratados adequadamente pela estrutura não devem acionar o registro em log superior ao nível DEBUG . As únicas situações que devem acionar o log no nível INFORMATIVE ou superior é quando um módulo ou aplicativo detecta um erro em seu próprio nível ou vindo de um nível inferior.
  • Quando uma condição que normalmente justificaria algum registro provavelmente ocorrerá muitas vezes, pode ser uma boa ideia implementar algum mecanismo de limitação de taxa para evitar o transbordamento dos logs com muitas cópias duplicadas das mesmas informações (ou muito semelhantes).
  • Perdas de conectividade de rede são consideradas comuns e totalmente esperadas, e não devem ser registradas gratuitamente. Uma perda de conectividade de rede que tenha consequências dentro de um aplicativo deve ser registrada no nível DEBUG ou VERBOSE (dependendo se as consequências são graves e inesperadas o suficiente para serem registradas em uma compilação de lançamento).
  • Ter um sistema de arquivos completo em um sistema de arquivos acessível para ou em nome de aplicativos de terceiros não deve ser registrado em um nível superior a INFORMATIVO.
  • Dados inválidos provenientes de qualquer fonte não confiável (incluindo qualquer arquivo em armazenamento compartilhado ou dados provenientes de uma conexão de rede) são considerados esperados e não devem acionar nenhum registro em um nível superior ao DEBUG quando for detectado como inválido (e mesmo assim o registro em log deve ser o mais limitado possível).
  • Quando usado em objetos String , o operador + cria implicitamente uma instância StringBuilder com o tamanho do buffer padrão (16 caracteres) e potencialmente outros objetos String temporários. Portanto, criar explicitamente objetos StringBuilder não é mais caro do que confiar no operador + padrão (e pode ser muito mais eficiente). Lembre-se de que o código que chama Log.v() é compilado e executado nas compilações de lançamento, incluindo a construção das strings, mesmo que os logs não estejam sendo lidos.
  • Qualquer registro destinado a ser lido por outras pessoas e estar disponível em versões de lançamento deve ser conciso, sem ser enigmático, e deve ser compreensível. Isso inclui todos os registros até o nível DEBUG .
  • Quando possível, continue registrando em uma única linha. Comprimentos de linha de até 80 ou 100 caracteres são aceitáveis. Evite comprimentos maiores que 130 ou 160 caracteres (incluindo o comprimento da tag), se possível.
  • Se o registro relatar sucesso, nunca use-o em níveis superiores a VERBOSE .
  • Se você estiver usando o log temporário para diagnosticar um problema difícil de reproduzir, mantenha-o no nível DEBUG ou VERBOSE e coloque-o entre blocos if que permitem desativá-lo em tempo de compilação.
  • Tenha cuidado com vazamentos de segurança no log. Evite registrar informações privadas. Em particular, evite registrar informações sobre conteúdo protegido. Isso é especialmente importante ao escrever código de estrutura, pois não é fácil saber antecipadamente o que será ou não informação privada ou conteúdo protegido.
  • Nunca use System.out.println() (ou printf() para código nativo). System.out e System.err são redirecionados para /dev/null , portanto, suas instruções de impressão não têm efeitos visíveis. No entanto, toda a construção de string que acontece para essas chamadas ainda é executada.
  • A regra de ouro do log é que seus logs não podem empurrar desnecessariamente outros logs para fora do buffer, assim como outros não podem empurrar os seus.

Regras de estilo Javatests

Siga as convenções de nomenclatura dos métodos de teste e use um sublinhado para separar o que está sendo testado do caso específico que está sendo testado. Esse estilo facilita ver quais casos estão sendo testados. Por exemplo:

testMethod_specificCase1 testMethod_specificCase2

void testIsDistinguishable_protanopia() {
    ColorMatcher colorMatcher = new ColorMatcher(PROTANOPIA)
    assertFalse(colorMatcher.isDistinguishable(Color.RED, Color.BLACK))
    assertTrue(colorMatcher.isDistinguishable(Color.X, Color.Y))
}