O Google tem o compromisso de promover a igualdade racial para as comunidades negras. Saiba como.

Estilo de código Java AOSP para contribuidores

Mantenha tudo organizado com as coleções Salve e categorize o conteúdo com base nas suas preferências.

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). 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 essas regras, mas esperamos que todos os novos códigos sejam compatíveis. Consulte Codificação com respeito para exemplos de terminologia a ser usada e evitada para um ecossistema mais inclusivo.

Ser consistente

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

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, ele 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 as exceções

Pode ser tentador escrever um 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 tratá-la, 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 tratamento específico varia dependendo do caso.

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

As 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.");
        }
      }
    
  • Lide com 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 deve 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 genérico ou Throwable (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 detectadas 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 ao código que você está chamando, o compilador não apontará que você precisa lidar com o erro de maneira diferente. Na maioria dos casos, você não deve lidar com diferentes tipos de exceções da mesma maneira.

A rara exceção a essa regra é o código de teste e o código de nível superior em que você deseja detectar todos os tipos de erros (para evitar que apareçam em uma interface do usuário ou para manter um trabalho em lote em execução). Nesses casos, você pode pegar uma Exception genérica (ou Throwable ) e lidar com o erro apropriadamente. Pense cuidadosamente 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. Divida o IO da análise e trate os erros separadamente em cada caso.
  • Lance novamente a exceção. Muitas vezes você não precisa capturar a exceção neste nível de qualquer maneira, 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á pegando uma exceção, não fique carrancudo. Sorriso! O compilador apenas tornou mais fácil para você detectar problemas de tempo de execução em seu código.

Não use finalizadores

Os 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 (principalmente de recursos externos), não há garantias de quando um finalizador será chamado (ou mesmo de que será chamado).

O Android não usa finalizadores. Na maioria dos casos, você pode usar um bom tratamento de exceção. 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 (consulte InputStream para obter um exemplo). Nesse caso, é apropriado, mas não obrigatório, imprimir uma mensagem de log curta do finalizador, desde que não seja esperado inundar os logs.

Importações totalmente qualificadas

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

  • import foo.*;

    Potencialmente reduz 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 do 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 foi alterada de forma importante e o código mais antigo pode usar um padrão ou biblioteca obsoleto. Ao trabalhar com esse código, não há problema em continuar com o estilo existente. No entanto, ao criar novos componentes, nunca use bibliotecas obsoletas.

Regras de estilo Java

Usar comentários padrão Javadoc

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

/*
 * Copyright 2022 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 tudo o que seu Javadoc disser for "sets Foo". Se o método faz algo mais complexo (como impor uma restrição ou tem um efeito colateral importante), você deve documentá-lo. Se não for óbvio o que a propriedade "Foo" significa, você deve documentá-la.

Todo método que você escrever, público ou não, se beneficiaria do Javadoc. 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 documento para a ferramenta Javadoc .

Escreva métodos curtos

Quando possí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 40 linhas ou mais, pense se ele pode ser quebrado sem prejudicar a estrutura do programa.

Definir campos em locais padrão

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

Escopo variável limite

Mantenha o escopo das variáveis ​​locais no mínimo. Isso aumenta a legibilidade e 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 em que são usadas pela primeira vez. Quase toda declaração de variável local deve conter um inicializador. Se você ainda não tem informações suficientes para inicializar uma variável de forma sensata, adie a declaração até que você tenha.

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 deve ser inicializada dentro de um bloco try. Se o valor deve ser usado fora do bloco try, 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 um motivo 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());
}

Extratos de importação de pedidos

A ordem das declaraçõ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:

  • Alfabeticamente dentro de cada agrupamento, com letras maiúsculas antes das 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 ordenação, o que significa que os IDEs estavam sempre alterando a ordenação ou os desenvolvedores de IDE tinham que desabilitar os recursos de gerenciamento de importação automática e manter manualmente as importações. Isso foi considerado ruim. Quando o estilo Java foi solicitado, os estilos preferidos variaram muito e o Android precisou simplesmente "escolher uma ordem e ser consistente". Então escolhemos um estilo, atualizamos o guia de estilo e fizemos os IDEs obedecê-lo. 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 de tal forma que:

  • As importações que as pessoas desejam ver primeiro tendem a estar no topo ( android ).
  • As importações que as pessoas desejam ver pelo menos tendem a estar 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 ao redor.

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 campo

  • Nomes de campos não públicos e não estáticos começam com m .
  • Nomes de campos estáticos começam com s .
  • Outros campos começam com uma letra minúscula.
  • 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 cinta padrão

Coloque chaves na mesma linha do código antes delas, não em sua própria linha:

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

Exigimos chaves em torno das instruções para uma condicional. Exceção: Se todo o 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!

Comprimento da linha limite

Cada linha de texto em seu código deve ter no máximo 100 caracteres. Embora haja muita discussão em torno dessa 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 recortar e colar.
  • As linhas de importação podem ultrapassar o limite porque os humanos raramente as veem (isso também simplifica a criação de ferramentas).

Use anotações Java padrão

As anotações devem preceder outros modificadores para o mesmo elemento de linguagem. Anotações de marcador simples (por exemplo, @Override ) podem ser listadas na mesma linha com o 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 com 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 é impossível eliminar um aviso. Se um aviso passar neste teste "impossível de eliminar", a anotação @SuppressWarnings deve ser usada para garantir que todos os avisos reflitam problemas reais no código.

    Quando uma anotação @SuppressWarnings é necessária, ela deve ser precedida de 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 nos quais a anotação se aplica.

Trate as 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 Mau
XmlHttpRequest XMLHTTPRequest
getCustomerId getCustomerID
classe Html classe HTML
url da string URL da string
identificação longa identificação longa

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

Usar 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 algo", certifique-se de incluir uma data específica ("Corrigir até novembro de 2005") ou um evento específico ("Remover 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 razoavelmente conciso. As instalações de registro fornecem cinco níveis diferentes de registro:

  • ERROR : Use quando algo fatal aconteceu, 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 a 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 para o usuário, mas provavelmente poderá ser recuperado sem perda de dados por meio da execução de alguma ação explícita, desde aguardar ou reiniciar um aplicativo até o download novamente uma nova versão de um aplicativo ou reiniciar o dispositivo. Este nível é sempre registrado. Os problemas que justificam o registro no nível WARNING também podem ser considerados para relatar a um servidor de coleta de estatísticas.
  • INFORMATIVE : Use para indicar que algo interessante aconteceu, ou seja, quando é detectada uma situação que pode ter um impacto generalizado, mas não necessariamente um erro. Essa condição só deve ser registrada por um módulo que acredita ser o mais autoritativo naquele domínio (para evitar o 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 necessário para reunir 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 lançamento e deve ser cercado por um if (LOCAL_LOG) ou if LOCAL_LOGD) , onde LOCAL_LOG[D] é definido em sua classe ou subcomponente, para que haja a possibilidade de desativar todos esses registros . Portanto, não deve haver lógica ativa em um bloco if (LOCAL_LOG) . Toda a construção de string 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) . Isso também é considerado aceitável, embora o nome não seja padrão.

  • VERBOSE : Use para todo o resto. Esse nível é registrado apenas 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 deve ser relatado apenas 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 registrar essa situação apenas no log DEBUG e somente se o registro fornecer informações que 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 onde a única informação registrada está contida em um código de erro. Isso é 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 log acima do nível DEBUG . As únicas situações que devem acionar o registro no nível INFORMATIVE ou superior é quando um módulo ou aplicativo detecta um erro em seu próprio nível ou proveniente de um nível inferior.
  • Quando uma condição que normalmente justificaria algum log é provável de ocorrer muitas vezes, pode ser uma boa ideia implementar algum mecanismo de limitação de taxa para evitar o estouro 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 em um aplicativo deve ser registrada no nível DEBUG ou VERBOSE (dependendo se as consequências são sérias e inesperadas o suficiente para serem registradas em um build 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 a DEBUG quando for detectado como inválido (e mesmo assim registrar deve ser o mais limitado possível).
  • Quando usado em objetos String , o operador + cria implicitamente uma instância StringBuilder com o tamanho de 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 em compilações de lançamento, incluindo a criação de strings, mesmo que os logs não estejam sendo lidos.
  • Qualquer registro destinado a ser lido por outras pessoas e estar disponível em compilações de lançamento deve ser conciso sem ser enigmático e deve ser compreensível. Isso inclui todos os logs 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 o use em níveis superiores a VERBOSE .
  • Se você estiver usando 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 no tempo de compilação.
  • Tenha cuidado com vazamentos de segurança através do 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 com antecedência o que será e o que não será 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 declaraçõ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 enviar desnecessariamente outros logs para fora do buffer, assim como outros não podem enviar os seus.

Regras de estilo de Javatests

Siga as convenções de nomenclatura do método de teste e use um sublinhado para separar o que está sendo testado do caso específico que está sendo testado. Esse estilo facilita a visualização de 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))
}