AOSP Java Code Style für Mitwirkende

Die Codestile auf dieser Seite sind strenge Regeln für das Beitragen von Java-Code zum Android Open Source Project (AOSP). Beiträge zur Android - Plattform , die im Allgemeinen nicht an diese Regeln halten werden nicht akzeptiert. Wir sind uns bewusst, dass nicht der gesamte vorhandene Code diesen Regeln entspricht, aber wir erwarten, dass der gesamte neue Code konform ist. Siehe Codierung mit Respekt für Beispiele der Terminologie zu verwenden und vermeiden Sie ein integratives Ökosystem.

Seien Sie konsequent

Eine der einfachsten Regeln ist KONSEQUENT SEIN. Wenn Sie Code bearbeiten, nehmen Sie sich ein paar Minuten Zeit, um sich den umgebenden Code anzusehen und seinen Stil zu bestimmen. Wenn dieser Code Räume um die verwendet , if Klauseln, sollten Sie auch. Wenn die Codekommentare kleine Kästchen mit Sternen haben, lassen Sie Ihre Kommentare auch kleine Kästchen mit Sternen um sich herum haben.

Der Sinn von Stilrichtlinien besteht darin, ein gemeinsames Codierungsvokabular zu haben, damit sich die Leser auf das konzentrieren können, was Sie sagen, anstatt darauf, wie Sie es sagen. Wir stellen hier globale Stilregeln vor, damit Sie das Vokabular kennen, aber auch der lokale Stil ist wichtig. Wenn der Code, den Sie einer Datei hinzufügen, sich drastisch von dem um sie herum vorhandenen Code unterscheidet, bringt dies die Leser aus dem Rhythmus, wenn sie ihn lesen. Versuchen Sie dies zu vermeiden.

Java-Sprachregeln

Android folgt den Standard-Java-Codierungskonventionen mit den unten beschriebenen zusätzlichen Regeln.

Ausnahmen nicht ignorieren

Es kann verlockend sein, Code zu schreiben, der eine Ausnahme ignoriert, wie zum Beispiel:

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

Tun Sie dies nicht. Während Sie vielleicht denken, dass Ihr Code niemals auf diese Fehlerbedingung stoßen wird oder dass es nicht wichtig ist, sie zu behandeln, erzeugt das Ignorieren dieser Art von Ausnahme Minen in Ihrem Code, die eines Tages von jemand anderem ausgelöst werden können. Sie müssen jede Ausnahme in Ihrem Code grundsätzlich behandeln; die konkrete Handhabung variiert je nach Fall.

"Immer hat jemand eine leere Klausel fängt sie ein gruseliges Gefühl haben sollten. Es gibt definitiv Zeiten , in denen es tatsächlich die richtige Sache zu tun ist, aber zumindest haben Sie darüber nachdenken. In Java Sie das gruselige Gefühl nicht entziehen können. "- James Gosling

Akzeptable Alternativen (in der Reihenfolge ihrer Präferenz) sind:

  • Werfen Sie die Ausnahme an den Aufrufer Ihrer Methode.
      void setServerPort(String value) throws NumberFormatException {
          serverPort = Integer.parseInt(value);
      }
    
  • Lösen Sie eine neue Ausnahme aus, die Ihrem Abstraktionsgrad entspricht.
      void setServerPort(String value) throws ConfigurationException {
        try {
            serverPort = Integer.parseInt(value);
        } catch (NumberFormatException e) {
            throw new ConfigurationException("Port " + value + " is not valid.");
        }
      }
    
  • Handelte den Fehler ordnungsgemäß und ersetzt einen entsprechenden Wert in dem catch {} Block.
      /** 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
        }
      }
    
  • Fangen Sie die Ausnahme und wirft eine neue Instanz von RuntimeException . Dies ist gefährlich, also tun Sie dies nur, wenn Sie sicher sind, dass beim Auftreten dieses Fehlers ein Absturz das Richtige ist.
      /** 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);
        }
      }
    
  • Als letzten Ausweg können Sie, wenn Sie sicher sind, dass das Ignorieren der Ausnahme angemessen ist, sie ignorieren, aber Sie müssen auch mit gutem Grund kommentieren, warum.
    /** 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.
        }
    }
    

Keine generischen Ausnahmen abfangen

Es kann verlockend sein, beim Abfangen von Ausnahmen faul zu sein und so etwas zu tun:

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

Tun Sie dies nicht. In fast allen Fällen ist es nicht angebracht generic zu fangen Exception oder Throwable (vorzugsweise nicht Throwable , weil es enthält Error Ausnahmen). Es ist gefährlich , weil es , dass Ausnahmen bedeutet , dass Sie nie (wie zB Laufzeit Ausnahmen erwartet ClassCastException ) in app-Ebene Fehlerbehandlung verfangen. Es verschleiert die Fehlerbehandlungseigenschaften Ihres Codes, dh wenn jemand einen neuen Ausnahmetyp in den aufgerufenen Code einfügt, weist der Compiler nicht darauf hin, dass Sie den Fehler anders behandeln müssen. In den meisten Fällen sollten Sie verschiedene Arten von Ausnahmen nicht auf die gleiche Weise behandeln.

Die seltene Ausnahme von dieser Regel sind Testcode und Top-Level-Code, bei dem Sie alle Arten von Fehlern abfangen möchten (um zu verhindern, dass sie in einer Benutzeroberfläche angezeigt werden, oder um einen Batch-Job auszuführen). In diesen Fällen können Sie generische fangen Exception (oder Throwable entsprechend) und behandeln den Fehler. Denken Sie jedoch sorgfältig darüber nach, bevor Sie dies tun, und fügen Sie Kommentare hinzu, in denen Sie erklären, warum es in diesem Zusammenhang sicher ist.

Alternativen zum Abfangen allgemeiner Ausnahmen:

  • Fangen jede Ausnahme separat als Teil eines Multi-Catch - Block, zum Beispiel:
    try {
        ...
    } catch (ClassNotFoundException | NoSuchMethodException e) {
        ...
    }
  • Refaktorieren Sie Ihren Code, um eine genauere Fehlerbehandlung mit mehreren Try-Blöcken zu ermöglichen. Trennen Sie die IO vom Parsing und behandeln Sie Fehler jeweils separat.
  • Die Ausnahme erneut auslösen. Oftmals müssen Sie die Ausnahme auf dieser Ebene ohnehin nicht abfangen, sondern lassen Sie die Methode sie einfach auslösen.

Denken Sie daran, dass Ausnahmen Ihr Freund sind! Wenn sich der Compiler beschwert, dass Sie keine Ausnahme abfangen, machen Sie keinen finsteren Blick. Lächeln! Der Compiler hat es Ihnen nur erleichtert, Laufzeitprobleme in Ihrem Code zu erkennen.

Keine Finalizer verwenden

Finalizer sind eine Möglichkeit, einen Codeabschnitt ausführen zu lassen, wenn ein Objekt Garbage Collection ist. Während Finalizer für die Bereinigung (insbesondere von externen Ressourcen) nützlich sein können, gibt es keine Garantien dafür, wann ein Finalizer aufgerufen wird (oder sogar, dass er überhaupt aufgerufen wird).

Android verwendet keine Finalizer. In den meisten Fällen können Sie stattdessen eine gute Ausnahmebehandlung verwenden. Wenn Sie unbedingt einen Finalizer benötigen, definiert eine close() Methode (oder dergleichen) und Dokument genau , wann diese Methode Bedürfnisse (siehe aufgerufen werden Input für ein Beispiel). In diesem Fall ist es angemessen, aber nicht erforderlich, eine kurze Protokollnachricht vom Finalizer zu drucken, solange nicht erwartet wird, dass die Protokolle überflutet werden.

Importe vollständig qualifizieren

Wenn Sie Klasse verwenden möchten Bar aus dem Paket foo , gibt es zwei Möglichkeiten , es zu importieren:

  • import foo.*;

    Reduziert möglicherweise die Anzahl der Importanweisungen.

  • import foo.Bar;

    Macht deutlich, welche Klassen verwendet werden und der Code ist für Betreuer besser lesbar.

Verwenden import foo.Bar; zum Importieren des gesamten Android-Codes. Eine explizite Ausnahme wird für Java - Standardbibliotheken (hergestellt java.util.* , java.io.* , etc.) und Unit - Test - Code ( junit.framework.* ).

Regeln für Java-Bibliotheken

Es gibt Konventionen für die Verwendung der Java-Bibliotheken und -Tools von Android. In einigen Fällen hat sich die Konvention in wichtigen Punkten geändert und älterer Code verwendet möglicherweise ein veraltetes Muster oder eine veraltete Bibliothek. Bei der Arbeit mit solchem ​​Code ist es in Ordnung, den bestehenden Stil fortzusetzen. Verwenden Sie beim Erstellen neuer Komponenten jedoch niemals veraltete Bibliotheken.

Regeln im Java-Stil

Javadoc-Standardkommentare verwenden

Jede Datei sollte oben eine Copyright-Angabe haben, gefolgt von Paket- und Import-Anweisungen (jeder Block durch eine Leerzeile getrennt) und schließlich die Klassen- oder Schnittstellendeklaration. Beschreiben Sie in den Javadoc-Kommentaren, was die Klasse oder Schnittstelle tut.

/*
 * Copyright 2021 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 {
    ...
}

Jede Klasse und nicht - triviale öffentliche Methode , dass Sie einen Javadoc - Kommentar mit mindestens einem Satz zu beschreiben , was die Klasse oder Methode enthält schreiben muss. Dieser Satz sollte mit einem beschreibenden Verb der dritten Person beginnen.

Beispiele

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

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

oder

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

Sie müssen nicht für triviale get und set - Methoden wie zum Schreib Javadoc müssen setFoo() , wenn Sie alle Ihre Javadoc „Sätze Foo“ ist sagen würde. Wenn die Methode etwas Komplexeres ausführt (z. B. eine Einschränkung erzwingt oder einen wichtigen Nebeneffekt hat), müssen Sie dies dokumentieren. Wenn nicht offensichtlich ist, was die Eigenschaft "Foo" bedeutet, sollten Sie dies dokumentieren.

Jede Methode, die Sie schreiben, ob öffentlich oder anderweitig, würde von Javadoc profitieren. Öffentliche Methoden sind Teil einer API und benötigen daher Javadoc. Android nicht einen bestimmten Stil zum Schreiben Javadoc Kommentare erzwingen, aber Sie sollten die Anweisungen in folgen Wie Doc Kommentare zu dem Javadoc - Tool zu schreiben .

Schreibe kurze Methoden

Wenn möglich, halten Sie die Methoden klein und fokussiert. Wir wissen, dass lange Methoden manchmal angemessen sind, daher gibt es keine feste Begrenzung der Methodenlänge. Wenn eine Methode etwa 40 Zeilen überschreitet, überlegen Sie, ob sie aufgebrochen werden kann, ohne die Struktur des Programms zu beschädigen.

Definieren Sie Felder an Standardorten

Definieren Sie Felder entweder am Anfang der Datei oder unmittelbar vor den Methoden, die sie verwenden.

Variablenbereich begrenzen

Beschränken Sie den Umfang lokaler Variablen auf ein Minimum. Dies erhöht die Lesbarkeit und Wartbarkeit Ihres Codes und verringert die Fehlerwahrscheinlichkeit. Deklarieren Sie jede Variable im innersten Block, der alle Verwendungen der Variablen einschließt.

Deklarieren Sie lokale Variablen an der Stelle, an der sie zum ersten Mal verwendet werden. Nahezu jede lokale Variablendeklaration sollte einen Initialisierer enthalten. Wenn Sie noch nicht über genügend Informationen verfügen, um eine Variable sinnvoll zu initialisieren, verschieben Sie die Deklaration bis dahin.

Die Ausnahme sind try-catch-Anweisungen. Wenn eine Variable mit dem Rückgabewert einer Methode initialisiert wird, die eine geprüfte Ausnahme auslöst, muss sie innerhalb eines try-Blocks initialisiert werden. Wenn der Wert außerhalb des try-Blocks verwendet werden muss, muss er vor dem try-Block deklariert werden, wo er noch nicht sinnvoll initialisiert werden kann:

// 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));

Sie können diesen Fall jedoch sogar vermeiden, indem Sie den try-catch-Block in einer Methode kapseln:

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

Deklarieren Sie Schleifenvariablen in der for-Anweisung selbst, es sei denn, es gibt einen zwingenden Grund, etwas anderes zu tun:

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

und

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

Importanweisungen bestellen

Die Reihenfolge der Importanweisungen ist:

  1. Android-Importe
  2. Die Einfuhren von Dritten ( com , junit , net , org )
  3. java und javax

Um genau den IDE-Einstellungen zu entsprechen, sollten die Importe wie folgt aussehen:

  • Alphabetisch innerhalb jeder Gruppierung, mit Großbuchstaben vor Kleinbuchstaben (z. B. Z vor a)
  • Getrennt durch eine Leerzeile zwischen jeder Hauptvereinigung ( android , com , junit , net , org , java , javax )

Ursprünglich gab es keine Stilanforderungen für die Reihenfolge, was bedeutete, dass IDEs entweder die Reihenfolge ständig änderten oder IDE-Entwickler die automatischen Importverwaltungsfunktionen deaktivieren und die Importe manuell verwalten mussten. Dies wurde als schlecht erachtet. Bei der Frage nach dem Java-Stil variierten die bevorzugten Stile stark und es kam darauf an, dass Android einfach "eine Reihenfolge auswählen und konsistent sein" musste. Also haben wir einen Stil ausgewählt, den Styleguide aktualisiert und die IDEs dazu gebracht, ihm zu gehorchen. Wir gehen davon aus, dass die Importe in allen Paketen ohne zusätzlichen Entwicklungsaufwand diesem Muster entsprechen, während IDE-Benutzer an dem Code arbeiten.

Wir haben diesen Stil so gewählt, dass:

  • Die Importe , dass die Menschen auf den ersten Blick wollen neigen dazu , an der Spitze (sein android ).
  • Die Importe , die Menschen zumindest aussehen wollen neigen dazu , am Boden (sein java ).
  • Menschen können dem Stil leicht folgen.
  • IDEs können dem Stil folgen.

Stellen Sie statische Importe über alle anderen Importe, die wie reguläre Importe geordnet sind.

Verwenden Sie Leerzeichen für den Einzug

Wir verwenden vier (4) Leerzeicheneinzüge für Blöcke und niemals Tabulatoren. Halten Sie sich im Zweifelsfall an den umgebenden Code.

Wir verwenden acht (8) Leerzeicheneinzüge für Zeilenumbrüche, einschließlich Funktionsaufrufe und Zuweisungen.

Empfohlen

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

Nicht empfohlen

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

Befolgen Sie die Namenskonventionen für Felder

  • Nicht-öffentliche, nicht-statische Feldnamen beginnen mit m .
  • Statische Feldnamen beginnen mit s .
  • Andere Felder beginnen mit einem Kleinbuchstaben.
  • Public final static Felder (Konstanten) sind ALL_CAPS_WITH_UNDERSCORES .

Zum Beispiel:

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

Verwenden Sie den Standard-Klammerstil

Setzen Sie geschweifte Klammern in dieselbe Zeile wie den Code davor, nicht in eine eigene Zeile:

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

Für eine Bedingung benötigen wir geschweifte Klammern um die Anweisungen. Ausnahme: Wenn das gesamte Conditional (die Bedingung und der Body) in eine Zeile passt, können Sie (aber nicht verpflichtet) alles in eine Zeile setzen. Dies ist zum Beispiel akzeptabel:

if (condition) {
    body();
}

und das ist akzeptabel:

if (condition) body();

aber das ist nicht akzeptabel:

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

Linienlänge begrenzen

Jede Textzeile in Ihrem Code sollte maximal 100 Zeichen lang sein. Während viel Diskussion dieser Regel umgeben ist, bleibt die Entscheidung , dass 100 Zeichen die maximal mit folgenden Ausnahmen ist:

  • Wenn eine Kommentarzeile einen Beispielbefehl oder eine Literal-URL mit mehr als 100 Zeichen enthält, kann diese Zeile zum leichteren Ausschneiden und Einfügen länger als 100 Zeichen sein.
  • Importzeilen können das Limit überschreiten, da sie selten von Menschen gesehen werden (dies vereinfacht auch das Schreiben von Werkzeugen).

Verwenden Sie standardmäßige Java-Anmerkungen

Anmerkungen sollten anderen Modifikatoren für dasselbe Sprachelement vorangehen. Einfache Marker Anmerkungen (zB @Override ) können auf der gleichen Linie mit dem Sprachelement angezeigt. Wenn mehrere Anmerkungen oder parametrisierte Anmerkungen vorhanden sind, listen Sie sie einzeln in alphabetischer Reihenfolge auf.

Android-Standardverfahren für die drei vordefinierten Anmerkungen in Java sind:

  • Verwenden Sie die @Deprecated Annotation , wenn die Verwendung des annotierten Elements abgeraten. Wenn Sie die Verwendung @Deprecated Anmerkung, müssen Sie auch einen haben @deprecated Javadoc - Tag , und es sollte eine alternative Implementierung nennen. Darüber hinaus, denken Sie daran , dass ein @Deprecated Methode noch funktionieren soll. Wenn Sie alten Code sehen, der eine hat @deprecated Javadoc - Tag, fügen Sie die @Deprecated Anmerkung.
  • Verwenden Sie die @Override Annotation , wann immer eine Methode , um die Erklärung oder Umsetzung von einer Oberklasse überschreibt. Zum Beispiel, wenn Sie die Verwendung @inheritdocs Javadoc - Tag, und leiten sich von einer Klasse (keine Schnittstelle), müssen Sie auch mit Anmerkungen versehen , dass die Methode überschreibt die Methode der übergeordneten Klasse.
  • Verwenden Sie die @SuppressWarnings Anmerkung nur unter Umständen , in denen es unmöglich ist , eine Warnung zu beseitigen. Wenn eine Warnung diesen passiert „unmöglich zu beseitigen“ -Test, die @SuppressWarnings muss Annotation verwendet werden, um sicherzustellen , dass alle Warnungen tatsächliche Probleme im Code zu reflektieren.

    Wenn eine @SuppressWarnings Anmerkung notwendig ist, muss es mit einem vorangestellt wird TODO Kommentar, der die „unmöglich zu beseitigen“ , erklärt Zustand. Dies identifiziert normalerweise eine anstößige Klasse, die eine umständliche Schnittstelle hat. Zum Beispiel:

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

    Wenn eine @SuppressWarnings Annotation erforderlich ist, Umgestalten des Code der Software - Elemente zu isolieren , wo die Anmerkung gilt.

Akronyme als Wörter behandeln

Behandeln Sie Akronyme und Abkürzungen als Wörter bei der Benennung von Variablen, Methoden und Klassen, um Namen lesbarer zu machen:

Gut Schlecht
XmlHttpRequest XMLHTTPRequest
getCustomerId getCustomerID
Klasse Html Klasse HTML
String-URL String-URL
lange id lange ID

Da sowohl die JDK- als auch die Android-Codebasis in Bezug auf Akronyme inkonsistent ist, ist es praktisch unmöglich, mit dem umgebenden Code konsistent zu sein. Behandeln Sie Akronyme daher immer als Wörter.

TODO-Kommentare verwenden

Verwenden TODO Kommentare zu Code, der nur vorübergehend ist, eine kurzfristige Lösung, oder gut genug , aber nicht perfekt. Diese Kommentare sollten die Zeichenfolge umfassen TODO in allen Kappen, gefolgt von einem Doppelpunkt:

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

und

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

Wenn Ihre TODO der Form „zu einem späteren Zeitpunkt tut etwas“ stellen Sie sicher , dass Sie entweder ein bestimmtes Datum ( „Fix vom November 2005“) oder ein bestimmtes Ereignis include ( „diesen Code entfernen , nachdem alle Produktionsmischern Protokoll V7 verstehen.“ ).

Sparsam protokollieren

Die Protokollierung ist zwar notwendig, wirkt sich aber negativ auf die Performance aus und verliert ihren Nutzen, wenn sie nicht einigermaßen knapp gehalten wird. Die Protokollierungseinrichtungen bieten fünf verschiedene Protokollierungsstufen:

  • ERROR : Verwenden Sie, wenn etwas fatal passiert ist, das heißt, etwas Benutzer sichtbare Folgen haben und werden einige Daten zu löschen , ohne die Deinstallation von Anwendungen, Abwischen der Datenpartitionen oder flasht das gesamte Gerät (oder schlechter) nicht wiederhergestellt werden. Dieser Level wird immer protokolliert. Probleme, die einige Protokollierung im rechtfertigen ERROR Ebene sind gute Kandidaten auf eine statistische Erfassung Server gemeldet werden.
  • WARNING : Verwenden Sie, wenn etwas Ernstes und Unerwartetes, das heißt, etwas , das den Benutzer sichtbare Konsequenzen haben wird , ist aber wahrscheinlich ohne Datenverlust wiederhergestellt werden kann durch eine explizite Aktion durchgeführt wird , im Bereich von Warten oder eine App den ganzen Weg zum erneuten Herunterladen Neustart eine neue Version einer App oder einen Neustart des Geräts. Dieser Level wird immer protokolliert. Probleme, die bei der Anmeldung justify WARNING Ebene könnten auch für die Berichterstattung an einen statistische Erfassung Server in Betracht gezogen werden.
  • INFORMATIVE : Verwenden Sie, dass etwas Interessantes passiert zu beachten, das heißt, wenn eine Situation erfasst wird, dass wahrscheinlich weitreichende Auswirkungen haben soll, ist allerdings nicht unbedingt ein Fehler. Eine solche Bedingung sollte nur von einem Modul protokolliert werden, das glaubt, dass es in dieser Domäne am autoritativesten ist (um eine doppelte Protokollierung durch nicht autoritative Komponenten zu vermeiden). Dieser Level wird immer protokolliert.
  • DEBUG : Verwenden Sie weiter zur Kenntnis , was auf dem Gerät geschieht , die relevant sein könnte , zu untersuchen und zu debuggen unerwartetem Verhalten. Protokollieren Sie nur, was erforderlich ist, um genügend Informationen über die Vorgänge mit Ihrer Komponente zu sammeln. Wenn Ihre Debugprotokolle das Protokoll dominieren, sollten Sie die ausführliche Protokollierung verwenden.

    Dieses Niveau wird protokolliert , selbst auf Release - Builds, und ist erforderlich , um ein umgeben zu sein , if (LOCAL_LOG) oder if LOCAL_LOGD) Block, wo LOCAL_LOG[D] ist in Ihrer Klasse oder Subkomponente definiert, so dass es eine Möglichkeit , alle solche Protokollierung zu deaktivieren . Daher muss es in einem nicht aktive Logik sein , if (LOCAL_LOG) Block. Alle String Gebäude für das Protokoll muss auch innerhalb der platziert werden , if (LOCAL_LOG) Block. Sie nicht die Protokollierung Anruf Refactoring in einem Methodenaufruf, wenn es geht um die Zeichenfolge verursachen Gebäude außerhalb des zu übernehmen , if (LOCAL_LOG) Block.

    Es gibt einige Code, der immer noch sagt , if (localLOGV) . Dies wird ebenfalls als akzeptabel angesehen, obwohl der Name nicht dem Standard entspricht.

  • VERBOSE : Verwenden Sie für alles andere. Diese Ebene wird nur protokolliert , auf Debug - Builds und sollte von einem umgeben sein , if (LOCAL_LOGV) Block (oder gleichwertig) , so dass es standardmäßig zusammengestellt werden kann. Jede Zeichenkette Gebäude ist gestrippt aus Release - Builds und Bedürfnisse innerhalb des erscheinen , if (LOCAL_LOGV) Block.

Anmerkungen

  • Innerhalb eines bestimmten Moduls, anders als bei der VERBOSE Ebene sollte ein Fehler nur einmal , wenn möglich gemeldet werden. Innerhalb einer einzelnen Kette von Funktionsaufrufen innerhalb eines Moduls sollte nur die innerste Funktion den Fehler zurückgeben, und Aufrufer im selben Modul sollten nur dann eine Protokollierung hinzufügen, wenn dies wesentlich zur Eingrenzung des Problems beiträgt.
  • In einer Kette von Modulen, die nicht an der VERBOSE Ebene, wenn ein Modul niedrigerer Ebene kommen ungültige Daten von einem Modul höherer Ebene erkennt, melden Sie sich das Modul niedrigerer Ebene sollte nur diese Situation zu dem DEBUG - Protokoll und nur , wenn die Protokollierung bietet Informationen, die dem Anrufer sonst nicht zur Verfügung stehen. Insbesondere müssen Situationen nicht protokolliert werden, in denen eine Ausnahme ausgelöst wird (die Ausnahme sollte alle relevanten Informationen enthalten) oder in denen die einzigen protokollierten Informationen in einem Fehlercode enthalten sind. Dies ist besonders wichtig bei der Interaktion zwischen Rahmen und Anwendungen und durch Anwendungen von Drittanbietern verursacht Bedingungen , das ordnungsgemäß durch den Rahmen behandelt werden , sollte die nicht auslösen Protokollierung höher als DEBUG Ebene. Die einzigen Situationen , die am Trigger Protokollierung sollte INFORMATIVE Pegel oder höher ist , wenn ein Modul einen Fehler oder App auf seiner Ebene oder aus Richtung einer niedrigeren Ebene erkennt.
  • Wenn eine Bedingung, die normalerweise eine gewisse Protokollierung rechtfertigen würde, wahrscheinlich viele Male auftritt, kann es eine gute Idee sein, einen Ratenbegrenzungsmechanismus zu implementieren, um zu verhindern, dass die Protokolle mit vielen doppelten Kopien derselben (oder sehr ähnlichen) Informationen überlaufen.
  • Verluste der Netzwerkkonnektivität gelten als häufig und werden in vollem Umfang erwartet und sollten nicht grundlos protokolliert werden. Ein Verlust der Netzwerkkonnektivität , die Folgen innerhalb einer App hat , sollte am angemeldet seine DEBUG oder VERBOSE Ebene (je nachdem , ob die Folgen sind schwerwiegend genug und unerwartet genug , um in einer Release - Build angemeldet zu sein).
  • Ein vollständiges Dateisystem in einem Dateisystem, auf das oder im Namen von Drittanbieter-Apps zugegriffen werden kann, sollte nicht auf einer höheren Ebene als INFORMATIV protokolliert werden.
  • Ungültige Daten aus jeder nicht vertrauenswürdigen Quelle (einschließlich einer beliebigen Datei auf gemeinsam genutzten Speicher oder Daten kommen über eine Netzverbindung) kommen wird erwartet , dass in Betracht gezogen und jegliche Protokollierung auf einem höheren Niveau als nicht auslösen sollte DEBUG , wenn festgestellt ist als ungültig (und selbst dann Protokollierung sollte so gering wie möglich sein).
  • Wenn auf verwendet String - Objekten, die + schafft Operator implizit eine StringBuilder - Instanz mit dem Standardpuffergröße (16 Zeichen) und möglicherweise anderen temporären String - Objekten. So explizit die Schaffung StringBuilder Objekte ist nicht teurer als die sich auf dem Standard - + Operator (und kann viel effizienter sein). Beachten Sie, dass Code, ruft Log.v() kompiliert und ausgeführt wird auf Release - Builds, einschließlich der Saiten bauen, auch wenn die Protokolle nicht gelesen werden.
  • Jede Protokollierung, die von anderen gelesen werden soll und in Release-Builds verfügbar sein soll, sollte knapp ohne kryptisch und verständlich sein. Dazu gehören alle Protokollierung bis zum DEBUG - Ebene.
  • Wenn möglich, loggen Sie sich weiterhin in einer einzigen Zeile ein. Zeilenlängen bis zu 80 oder 100 Zeichen sind akzeptabel. Vermeiden Sie nach Möglichkeit Längen von mehr als etwa 130 oder 160 Zeichen (einschließlich der Länge des Tags).
  • Wenn Berichte Erfolge anmelden, es nie auf ein Niveau verwendet höher als VERBOSE .
  • Wenn Sie temporäre Protokollierung verwenden um ein Problem zu diagnostizieren , die schwer zu reproduzieren ist, halten Sie es in den DEBUG oder VERBOSE Ebene und legen Sie es , wenn Blöcke , die zum Deaktivieren es bei der Kompilierung erlauben.
  • Seien Sie vorsichtig bei Sicherheitslecks durch das Protokoll. Vermeiden Sie das Protokollieren privater Informationen. Vermeiden Sie insbesondere das Protokollieren von Informationen zu geschützten Inhalten. Dies ist besonders wichtig beim Schreiben von Framework-Code, da es nicht einfach ist, im Voraus zu wissen, was private Informationen oder geschützte Inhalte sein werden und was nicht.
  • Verwenden Sie niemals System.out.println() (oder printf() für nativen Code). System.out und System.err erhalten umgeleitet /dev/null , so dass Ihre Druck Aussagen keine sichtbaren Auswirkungen. Der gesamte Stringaufbau, der für diese Aufrufe stattfindet, wird jedoch weiterhin ausgeführt.
  • Die goldene Regel des Loggings lautet, dass Ihre Logs andere Logs nicht unnötig aus dem Puffer schieben dürfen, genauso wie andere Ihre Logs nicht verdrängen.

Stilregeln für Javatests

Befolgen Sie die Benennungskonventionen für Testmethoden und verwenden Sie einen Unterstrich, um das Getestete von dem zu testenden Fall zu trennen. Dieser Stil macht es einfacher zu sehen, welche Fälle getestet werden. Zum Beispiel:

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