Estilo de código Java AOSP para contribuyentes

Los estilos de código de esta página son reglas estrictas para contribuir con código Java al Proyecto de código abierto de Android (AOSP). Por lo general , no se aceptan contribuciones a la plataforma Android que no cumplan con estas reglas. Reconocemos que no todo el código existente sigue estas reglas, pero esperamos que todo el código nuevo las cumpla. Consulte Codificar con respeto para ver ejemplos de terminología que se debe utilizar y evitar para lograr un ecosistema más inclusivo.

Se consistente

Una de las reglas más simples es SER CONSISTENTE. Si está editando código, tómese unos minutos para observar el código circundante y determinar su estilo. Si ese código usa espacios alrededor de las cláusulas if , tú también deberías hacerlo. Si los comentarios del código tienen pequeños cuadros de estrellas alrededor, haga que sus comentarios también tengan pequeños cuadros de estrellas alrededor.

El objetivo de tener pautas de estilo es tener un vocabulario común de codificación, de modo que los lectores puedan concentrarse en lo que estás diciendo, en lugar de en cómo lo estás diciendo. Aquí presentamos reglas de estilo globales para que conozca el vocabulario, pero el estilo local también es importante. Si el código que agrega a un archivo se ve drásticamente diferente del código existente a su alrededor, los lectores pierden el ritmo cuando lo leen. Intenta evitar esto.

reglas del lenguaje java

Android sigue las convenciones de codificación estándar de Java con las reglas adicionales que se describen a continuación.

No ignores las excepciones

Puede resultar tentador escribir código que ignore una excepción, como por ejemplo:

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

No hagas esto. Si bien puede pensar que su código nunca encontrará esta condición de error o que no es importante manejarla, ignorar este tipo de excepción crea minas en su código que alguien más podrá activar algún día. Debes manejar cada excepción en tu código siguiendo principios; el manejo específico varía según el caso.

" Cada vez que alguien tiene una cláusula de captura vacía debería tener una sensación espeluznante. Definitivamente hay ocasiones en las que en realidad es lo correcto, pero al menos hay que pensar en ello. En Java no puedes escapar de la sensación espeluznante. " -James Gosling

Las alternativas aceptables (en orden de preferencia) son:

  • Lanza la excepción a la persona que llama a tu método.
      void setServerPort(String value) throws NumberFormatException {
          serverPort = Integer.parseInt(value);
      }
    
  • Lanza una nueva excepción que sea apropiada para tu nivel de abstracción.
      void setServerPort(String value) throws ConfigurationException {
        try {
            serverPort = Integer.parseInt(value);
        } catch (NumberFormatException e) {
            throw new ConfigurationException("Port " + value + " is not valid.");
        }
      }
    
  • Maneje el error con elegancia y sustituya un valor apropiado en el bloque 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
        }
      }
    
  • Capte la excepción y lance una nueva instancia de RuntimeException . Esto es peligroso, así que hágalo sólo si está seguro de que si se produce este error, lo correcto es bloquearse.
      /** 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, si está seguro de que ignorar la excepción es apropiado, puede ignorarla, pero también debe comentar el motivo y una buena razón.
    /** 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.
        }
    }
    

No detectes excepciones genéricas

Puede resultar tentador ser perezoso al detectar excepciones y hacer algo como esto:

  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!
  }

No hagas esto. En casi todos los casos, no es apropiado detectar Exception genéricas o Throwable (preferiblemente no Throwable porque incluyen excepciones Error ). Es peligroso porque significa que las excepciones que nunca esperó (incluidas las excepciones de tiempo de ejecución como ClassCastException ) quedan atrapadas en el manejo de errores a nivel de aplicación. Oculta las propiedades de manejo de fallas de su código, lo que significa que si alguien agrega un nuevo tipo de excepción en el código que está llamando, el compilador no señalará que necesita manejar el error de manera diferente. En la mayoría de los casos, no debería manejar diferentes tipos de excepciones de la misma manera.

La rara excepción a esta regla es el código de prueba y el código de nivel superior en los que desea detectar todo tipo de errores (para evitar que aparezcan en una interfaz de usuario o para mantener un trabajo por lotes en ejecución). En estos casos, puede detectar Exception genérica (o Throwable ) y manejar el error de manera adecuada. Sin embargo, piénselo detenidamente antes de hacer esto y escriba comentarios que expliquen por qué es seguro en este contexto.

Alternativas para detectar excepciones genéricas:

  • Capture cada excepción por separado como parte de un bloque de captura múltiple, por ejemplo:
    try {
        ...
    } catch (ClassNotFoundException | NoSuchMethodException e) {
        ...
    }
  • Refactorice su código para tener un manejo de errores más detallado, con múltiples bloques de prueba. Divida la IO del análisis y maneje los errores por separado en cada caso.
  • Vuelva a lanzar la excepción. Muchas veces no es necesario detectar la excepción en este nivel de todos modos, simplemente deja que el método la genere.

¡Recuerda que las excepciones son tus amigas! Cuando el compilador se queja de que no detecta una excepción, no frunca el ceño. ¡Sonrisa! El compilador simplemente le facilitó la detección de problemas de tiempo de ejecución en su código.

No uses finalizadores

Los finalizadores son una forma de ejecutar una porción de código cuando un objeto se recolecta como basura. Si bien los finalizadores pueden ser útiles para la limpieza (particularmente de recursos externos), no hay garantías de cuándo se llamará a un finalizador (o incluso de que se llamará).

Android no utiliza finalizadores. En la mayoría de los casos, puede utilizar un buen manejo de excepciones. Si es absolutamente necesario un finalizador, defina un método close() (o similar) y documente exactamente cuándo se debe llamar a ese método (consulte InputStream para ver un ejemplo). En este caso, es apropiado, aunque no obligatorio, imprimir un breve mensaje de registro desde el finalizador, siempre y cuando no se espere que inunde los registros.

Importaciones totalmente calificadas

Cuando desee utilizar la clase Bar del paquete foo , hay dos formas posibles de importarla:

  • import foo.*;

    Reduce potencialmente el número de declaraciones de importación.

  • import foo.Bar;

    Hace obvio qué clases se utilizan y el código es más legible para los mantenedores.

Utilice import foo.Bar; para importar todo el código de Android. Se hace una excepción explícita para las bibliotecas estándar de Java ( java.util.* , java.io.* , etc.) y el código de prueba unitaria ( junit.framework.* ).

reglas de la biblioteca java

Existen convenciones para utilizar las bibliotecas y herramientas Java de Android. En algunos casos, la convención ha cambiado de manera importante y el código más antiguo puede utilizar un patrón o biblioteca en desuso. Cuando se trabaja con dicho código, está bien continuar con el estilo existente. Sin embargo, al crear nuevos componentes, nunca utilice bibliotecas obsoletas.

reglas de estilo java

Utilice comentarios estándar de Javadoc

Cada archivo debe tener una declaración de derechos de autor en la parte superior, seguida de declaraciones de paquete e importación (cada bloque separado por una línea en blanco) y finalmente la declaración de clase o interfaz. En los comentarios de Javadoc, describa qué hace la clase o interfaz.

/*
 * 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 clase y método público no trivial que escriba debe contener un comentario Javadoc con al menos una oración que describa lo que hace la clase o el método. Esta oración debe comenzar con un verbo descriptivo en tercera persona.

Ejemplos

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

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

o

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

No es necesario escribir Javadoc para métodos triviales de obtención y configuración como setFoo() si todo lo que su Javadoc dice es "conjuntos Foo". Si el método hace algo más complejo (como imponer una restricción o tiene un efecto secundario importante), entonces debe documentarlo. Si no es obvio qué significa la propiedad "Foo", debes documentarlo.

Cada método que escriba, público o no, se beneficiaría de Javadoc. Los métodos públicos son parte de una API y, por lo tanto, requieren Javadoc. Android no impone un estilo específico para escribir comentarios Javadoc, pero debes seguir las instrucciones en Cómo escribir comentarios de documentos para la herramienta Javadoc .

Escribir métodos cortos

Cuando sea posible, mantenga los métodos pequeños y enfocados. Reconocemos que los métodos largos a veces son apropiados, por lo que no se impone ningún límite estricto a la longitud del método. Si un método supera las 40 líneas aproximadamente, piense si se puede dividir sin dañar la estructura del programa.

Definir campos en lugares estándar

Defina campos en la parte superior del archivo o inmediatamente antes de los métodos que los utilizan.

Limitar el alcance de la variable

Mantenga el alcance de las variables locales al mínimo. Esto aumenta la legibilidad y el mantenimiento de su código y reduce la probabilidad de error. Declare cada variable en el bloque más interno que encierra todos los usos de la variable.

Declare las variables locales en el punto donde se utilizan por primera vez. Casi todas las declaraciones de variables locales deben contener un inicializador. Si aún no tiene suficiente información para inicializar una variable de manera sensata, posponga la declaración hasta que la tenga.

La excepción son las declaraciones try-catch. Si una variable se inicializa con el valor de retorno de un método que genera una excepción marcada, se debe inicializar dentro de un bloque try. Si el valor debe usarse fuera del bloque try, entonces debe declararse antes del bloque try, donde aún no se puede inicializar de manera 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));

Sin embargo, puedes incluso evitar este caso encapsulando el bloque try-catch en un 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 variables de bucle en la propia declaración for a menos que haya una razón convincente para hacer lo contrario:

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

y

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

Declaraciones de importación de pedidos

El orden de las declaraciones de importación es:

  1. importaciones de Android
  2. Importaciones de terceros ( com , junit , net , org )
  3. java y javax

Para coincidir exactamente con la configuración del IDE, las importaciones deben ser:

  • Alfabéticamente dentro de cada grupo, con letras mayúsculas antes de las minúsculas (por ejemplo, Z antes de a)
  • Separados por una línea en blanco entre cada grupo principal ( android , com , junit , net , org , java , javax )

Originalmente, no había ningún requisito de estilo en el orden, lo que significaba que los IDE siempre cambiaban el orden o los desarrolladores de IDE tenían que desactivar las funciones de administración automática de importaciones y mantener las importaciones manualmente. Esto se consideró malo. Cuando se preguntó el estilo de Java, los estilos preferidos variaron enormemente y todo se redujo a que Android necesitaba simplemente "elegir un orden y ser coherente". Así que elegimos un estilo, actualizamos la guía de estilo e hicimos que los IDE lo obedecieran. Esperamos que a medida que los usuarios de IDE trabajen en el código, las importaciones en todos los paquetes coincidirán con este patrón sin esfuerzo de ingeniería adicional.

Elegimos este estilo de modo que:

  • Las importaciones que la gente quiere ver primero tienden a estar en la parte superior ( android ).
  • Las importaciones que la gente quiere ver al menos tienden a estar en la parte inferior ( java ).
  • Los humanos pueden seguir fácilmente el estilo.
  • Los IDE pueden seguir el estilo.

Coloque las importaciones estáticas por encima de todas las demás importaciones ordenadas de la misma manera que las importaciones regulares.

Usar espacios para sangría

Usamos sangrías de cuatro (4) espacios para bloques y nunca tabulaciones. En caso de duda, sea coherente con el código circundante.

Usamos ocho (8) sangrías de espacio para los saltos de línea, incluidas las llamadas y asignaciones de funciones.

Recomendado

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

No recomendado

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

Siga las convenciones de nomenclatura de campos

  • Los nombres de campos no públicos y no estáticos comienzan con m .
  • Los nombres de campos estáticos comienzan con s .
  • Otros campos comienzan con una letra minúscula.
  • Los campos finales estáticos (constantes, profundamente inmutables) son ALL_CAPS_WITH_UNDERSCORES .

Por ejemplo:

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;
}

Utilice el estilo de corsé estándar

Coloque llaves en la misma línea que el código anterior, no en su propia línea:

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

Requerimos llaves alrededor de las declaraciones para un condicional. Excepción: si todo el condicional (la condición y el cuerpo) cabe en una línea, puedes (pero no estás obligado a) ponerlo todo en una sola línea. Por ejemplo, esto es aceptable:

if (condition) {
    body();
}

y esto es aceptable:

if (condition) body();

pero esto no es aceptable:

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

Limitar la longitud de la línea

Cada línea de texto de su código debe tener como máximo 100 caracteres. Si bien se ha debatido mucho sobre esta regla, la decisión sigue siendo que el máximo es 100 caracteres con las siguientes excepciones :

  • Si una línea de comentario contiene un comando de ejemplo o una URL literal de más de 100 caracteres, esa línea puede tener más de 100 caracteres para facilitar el corte y pegado.
  • Las líneas de importación pueden superar el límite porque los humanos rara vez las ven (esto también simplifica la escritura de herramientas).

Utilice anotaciones estándar de Java

Las anotaciones deben preceder a otros modificadores para el mismo elemento del lenguaje. Las anotaciones de marcador simples (por ejemplo, @Override ) se pueden enumerar en la misma línea que el elemento de idioma. Si hay varias anotaciones o anotaciones parametrizadas, enumérelas una por línea en orden alfabético.

Las prácticas estándar de Android para las tres anotaciones predefinidas en Java son:

  • Utilice la anotación @Deprecated siempre que se desaconseje el uso del elemento anotado. Si utiliza la anotación @Deprecated , también debe tener una etiqueta Javadoc @deprecated y debe nombrar una implementación alternativa. Además, recuerde que se supone que un método @Deprecated todavía funciona . Si ve un código antiguo que tiene una etiqueta Javadoc @deprecated , agregue la anotación @Deprecated .
  • Utilice la anotación @Override siempre que un método anule la declaración o implementación de una superclase. Por ejemplo, si usa la etiqueta Javadoc @inheritdocs y deriva de una clase (no de una interfaz), también debe anotar que el método anula el método de la clase principal.
  • Utilice la anotación @SuppressWarnings solo en circunstancias en las que sea imposible eliminar una advertencia. Si una advertencia pasa esta prueba de "imposible de eliminar", se debe utilizar la anotación @SuppressWarnings para garantizar que todas las advertencias reflejen los problemas reales en el código.

    Cuando es necesaria una anotación @SuppressWarnings , debe tener como prefijo un comentario TODO que explique la condición "imposible de eliminar". Esto normalmente identifica una clase infractora que tiene una interfaz incómoda. Por ejemplo:

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

    Cuando se requiere una anotación @SuppressWarnings , refactorice el código para aislar los elementos de software donde se aplica la anotación.

Trate las siglas como palabras

Trate las siglas y abreviaturas como palabras al nombrar variables, métodos y clases para que los nombres sean más legibles:

Bien Malo
Solicitud XMLHttp Solicitud XMLHTTP
obtenerId.DeCliente obtener ID de cliente
clase HTML clase HTML
URL de cadena URL de cadena
identificación larga identificación larga

Como tanto el código base de JDK como el de Android son inconsistentes en cuanto a las siglas, es prácticamente imposible ser coherente con el código circundante. Por lo tanto, trate siempre las siglas como palabras.

Utilice comentarios TODO

Utilice comentarios TODO para código que sea temporal, una solución a corto plazo o lo suficientemente bueno pero no perfecto. Estos comentarios deben incluir la cadena TODO en mayúsculas, seguida de dos puntos:

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

y

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

Si su TODO tiene el formato "En una fecha futura, haga algo", asegúrese de incluir una fecha específica ("Reparar en noviembre de 2005") o un evento específico ("Eliminar este código después de que todos los mezcladores de producción comprendan el protocolo V7". ).

Registre con moderación

Si bien el registro es necesario, tiene un impacto negativo en el rendimiento y pierde su utilidad si no se mantiene razonablemente conciso. Las instalaciones de tala ofrecen cinco niveles diferentes de tala:

  • ERROR : Úselo cuando haya sucedido algo fatal, es decir, algo tendrá consecuencias visibles para el usuario y no será recuperable sin eliminar algunos datos, desinstalar aplicaciones, borrar las particiones de datos o actualizar todo el dispositivo (o algo peor). Este nivel siempre se registra. Los problemas que justifican algunos registros en el nivel ERROR son buenos candidatos para ser reportados a un servidor de recopilación de estadísticas.
  • WARNING : Úselo cuando sucedió algo grave e inesperado, es decir, algo que tendrá consecuencias visibles para el usuario pero que probablemente se pueda recuperar sin pérdida de datos al realizar alguna acción explícita, que va desde esperar o reiniciar una aplicación hasta volver a descargarla. una nueva versión de una aplicación o reiniciar el dispositivo. Este nivel siempre se registra. Los problemas que justifican el registro en el nivel WARNING también podrían considerarse para informar a un servidor de recopilación de estadísticas.
  • INFORMATIVE : Se utiliza para señalar que sucedió algo interesante, es decir, cuando se detecta una situación que probablemente tenga un impacto generalizado, aunque no necesariamente sea un error. Tal condición sólo debe ser registrada por un módulo que crea que es el más autorizado en ese dominio (para evitar registros duplicados por parte de componentes no autorizados). Este nivel siempre se registra.
  • DEBUG : Úselo para observar con más detalle lo que sucede en el dispositivo que podría ser relevante para investigar y depurar comportamientos inesperados. Registre sólo lo necesario para recopilar suficiente información sobre lo que sucede con su componente. Si sus registros de depuración dominan el registro, entonces debe utilizar el registro detallado.

    Este nivel se registra incluso en las versiones de lanzamiento y debe estar rodeado por un bloque if (LOCAL_LOG) o if LOCAL_LOGD) , donde LOCAL_LOG[D] está definido en su clase o subcomponente, de modo que exista la posibilidad de deshabilitar todos esos registros. . Por lo tanto, no debe haber ninguna lógica activa en un bloque if (LOCAL_LOG) . Toda la creación de cadenas para el registro también debe colocarse dentro del bloque if (LOCAL_LOG) . No refactorice la llamada de registro en una llamada a un método si esto va a provocar que la creación de la cadena se realice fuera del bloque if (LOCAL_LOG) .

    Hay un código que todavía dice if (localLOGV) . Esto también se considera aceptable, aunque el nombre no es estándar.

  • VERBOSE : Úselo para todo lo demás. Este nivel solo se registra en compilaciones de depuración y debe estar rodeado por un bloque if (LOCAL_LOGV) (o equivalente) para que pueda compilarse de forma predeterminada. Cualquier compilación de cadenas se elimina de las compilaciones de lanzamiento y debe aparecer dentro del bloque if (LOCAL_LOGV) .

Notas

  • Dentro de un módulo determinado, excepto en el nivel VERBOSE , un error solo debe informarse una vez si es posible. Dentro de una única cadena de llamadas a funciones dentro de un módulo, solo la función más interna debería devolver el error, y las personas que llaman en el mismo módulo solo deberían agregar algo de registro si eso ayuda significativamente a aislar el problema.
  • En una cadena de módulos, que no sea en el nivel VERBOSE , cuando un módulo de nivel inferior detecta datos no válidos provenientes de un módulo de nivel superior, el módulo de nivel inferior solo debe registrar esta situación en el registro DEBUG , y solo si el registro proporciona información que de otro modo no estaría disponible para la persona que llama. Específicamente, no es necesario registrar situaciones en las que se produce una excepción (la excepción debe contener toda la información relevante) o en las que la única información que se registra está contenida en un código de error. Esto es especialmente importante en la interacción entre el marco y las aplicaciones, y las condiciones causadas por aplicaciones de terceros que el marco maneja adecuadamente no deberían desencadenar un registro superior al nivel DEBUG . Las únicas situaciones que deberían activar el registro en el nivel INFORMATIVE o superior es cuando un módulo o aplicación detecta un error en su propio nivel o proveniente de un nivel inferior.
  • Cuando es probable que ocurra muchas veces una condición que normalmente justificaría algún registro, puede ser una buena idea implementar algún mecanismo de limitación de velocidad para evitar que los registros se desborden con muchas copias duplicadas de la misma (o muy similar) información.
  • Las pérdidas de conectividad de red se consideran comunes, se esperan y no deben registrarse de forma gratuita. Una pérdida de conectividad de red que tiene consecuencias dentro de una aplicación debe registrarse en el nivel DEBUG o VERBOSE (dependiendo de si las consecuencias son lo suficientemente graves e inesperadas como para registrarse en una versión de lanzamiento).
  • Tener un sistema de archivos completo en un sistema de archivos al que pueden acceder aplicaciones de terceros o en nombre de ellas no debe registrarse en un nivel superior a INFORMATIVO.
  • Los datos no válidos provenientes de cualquier fuente que no sea de confianza (incluido cualquier archivo en almacenamiento compartido o datos provenientes de una conexión de red) se consideran esperados y no deberían activar ningún registro en un nivel superior a DEBUG cuando se detecta que no son válidos (e incluso entonces el registro debe ser lo más limitado posible).
  • Cuando se usa en objetos String , el operador + crea implícitamente una instancia StringBuilder con el tamaño de búfer predeterminado (16 caracteres) y potencialmente otros objetos String temporales. Por lo tanto, crear explícitamente objetos StringBuilder no es más costoso que confiar en el operador + predeterminado (y puede ser mucho más eficiente). Tenga en cuenta que el código que llama a Log.v() se compila y ejecuta en las versiones de lanzamiento, incluida la creación de cadenas, incluso si los registros no se leen.
  • Cualquier registro destinado a ser leído por otras personas y a estar disponible en versiones de lanzamiento debe ser conciso sin ser críptico y debe ser comprensible. Esto incluye todos los registros hasta el nivel DEBUG .
  • Cuando sea posible, siga iniciando sesión en una sola línea. Se aceptan líneas de hasta 80 o 100 caracteres. Si es posible, evite longitudes superiores a 130 o 160 caracteres (incluida la longitud de la etiqueta).
  • Si el registro informa éxito, nunca lo use en niveles superiores a VERBOSE .
  • Si está utilizando el registro temporal para diagnosticar un problema que es difícil de reproducir, manténgalo en el nivel DEBUG o VERBOSE y encierrelo con bloques if que permitan deshabilitarlo en el momento de la compilación.
  • Tenga cuidado con las fugas de seguridad a través del registro. Evite registrar información privada. En particular, evite registrar información sobre contenido protegido. Esto es especialmente importante al escribir código marco, ya que no es fácil saber de antemano qué será y qué no será información privada o contenido protegido.
  • Nunca utilice System.out.println() (o printf() para código nativo). System.out y System.err son redirigidos a /dev/null , por lo que sus declaraciones impresas no tienen efectos visibles. Sin embargo, toda la construcción de cadenas que ocurre para estas llamadas aún se ejecuta.
  • La regla de oro del registro es que sus registros no pueden sacar innecesariamente otros registros del búfer, del mismo modo que otros no pueden sacar el suyo.

Reglas de estilo de pruebas de Java

Siga las convenciones de nomenclatura de los métodos de prueba y utilice un guión bajo para separar lo que se está probando del caso específico que se está probando. Este estilo facilita ver qué casos se están probando. Por ejemplo:

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))
}