Az ezen az oldalon található kódstílusok szigorú szabályokat tartalmaznak az Android Open Source Project (AOSP) Java kódjának hozzájárulásához. Az Android platformhoz való hozzájárulásokat, amelyek nem tartják be ezeket a szabályokat, általában nem fogadják el. Elismerjük, hogy nem minden meglévő kód követi ezeket a szabályokat, de elvárjuk, hogy minden új kód megfeleljen ezeknek. Lásd a Tiszteletteljes kódolás című fejezetet, ahol példákat találsz a használni és kerülni kívánt terminológiára egy befogadóbb ökoszisztéma érdekében.
- Légy következetes
- Java nyelvi szabályok
- Ne hagyja figyelmen kívül a kivételeket
- Ne kapjuk el az általános kivételeket
- Ne használj finalizátorokat
- Fully qualify imports
- Java könyvtári szabályok
- Java stílusszabályok
- Rövid módszereket írjon
- Mezők definiálása a szokásos helyeken
- Változók hatókörének korlátozása
- Order import statements
- Use spaces for indentation
- Follow field naming conventions
- Use standard brace style
- Limit line length
- Szokásos Java megjegyzések használata
- Treat acronyms as words
- Takarékosan naplózzunk
- Jegyzetek
- Javatests stílusszabályok
Légy következetes
Az egyik legegyszerűbb szabály: Légy következetes. Ha kódot szerkeszt, szánjon néhány percet arra, hogy megnézze a környező kódot, és meghatározza annak stílusát. Ha az a kód szóközöket használ a if
záradékok körül, akkor neked is ezt kellene tenned. Ha a kódkommentárokat kis csillagdobozok veszik körül, akkor a te kommentjeidben is legyenek kis csillagdobozok.
A stílusirányelvek lényege, hogy legyen egy közös kódolási szótár, hogy az olvasók arra koncentrálhassanak, amit mondasz, ne pedig arra, hogy hogyan mondod. Itt globális stílusszabályokat mutatunk be, hogy ismerje a szókincset, de a helyi stílus is fontos. Ha a fájlhoz hozzáadott kód drasztikusan eltér a körülötte lévő meglévő kódtól, az olvasókat kizökkenti a ritmusból, amikor elolvassák. Próbálja ezt elkerülni.
Java nyelvi szabályok
Az Android a szabványos Java kódolási konvenciókat követi az alább ismertetett további szabályokkal.
Ne hagyja figyelmen kívül a kivételeket
Csábító lehet olyan kódot írni, amely figyelmen kívül hagy egy kivételt, például:
void setServerPort(String value) { try { serverPort = Integer.parseInt(value); } catch (NumberFormatException e) { } }
Ne tegye ezt. Bár azt gondolhatja, hogy a kódja soha nem fog találkozni ezzel a hibaállapottal, vagy hogy nem fontos kezelni, az ilyen típusú kivételek figyelmen kívül hagyása aknákat teremt a kódjában, amelyeket egy nap valaki más is kiválthat. A kódodban minden kivételt elvszerűen kell kezelned; a konkrét kezelés az esettől függően változik.
“Bármikor, amikor valakinek üres catch klauzulája van, legyen egy hátborzongató érzése. Biztosan vannak olyan esetek, amikor valóban ez a helyes, de legalább el kell gondolkodni rajta. Javában nem lehet megmenekülni a hátborzongató érzéstől.” – James Gosling
Az elfogadható alternatívák (preferencia sorrendben) a következők:
- Dobd a kivételt a módszer hívójának.
void setServerPort(String value) throws NumberFormatException { serverPort = Integer.parseInt(value); }
- Dobj egy új, az absztrakciós szintnek megfelelő kivételt.
void setServerPort(String value) throws ConfigurationException { try { serverPort = Integer.parseInt(value); } catch (NumberFormatException e) { throw new ConfigurationException("Port " + value + " is not valid."); } }
- Kezelje a hibát elegánsan, és helyettesítsen egy megfelelő értéket a
catch {}
blokkban./** 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 } }
- Kapja el a kivételt, és dobjon egy új példányt a
RuntimeException
. Ez veszélyes, ezért csak akkor tedd meg, ha biztos vagy benne, hogy a hiba bekövetkezése esetén a megfelelő dolog az összeomlás./** 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); } }
- Végső megoldásként, ha biztos vagy benne, hogy a kivétel figyelmen kívül hagyása a megfelelő, akkor figyelmen kívül hagyhatod, de azt is kommentálnod kell, hogy miért, jó indoklással.
/** 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. }}
Ne kapjuk el az általános kivételeket
Csábító lehet lustának lenni a kivételek elfogásakor, és valami ilyesmit tenni:
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! }
Ne tegye ezt. Szinte minden esetben helytelen általános Exception
vagy Throwable
(lehetőleg ne Throwable
, mert az Error
kivételeket tartalmaz). Ez azért veszélyes, mert azt jelenti, hogy a soha nem várt kivételek (beleértve az olyan futásidejű kivételeket is, mint a ClassCastException
) az alkalmazásszintű hibakezelés során elkapásra kerülnek. Elhomályosítja a kódod hibakezelési tulajdonságait, ami azt jelenti, hogy ha valaki egy új típusú kivételt ad hozzá az általad hívott kódhoz, a fordító nem fogja felhívni a figyelmet arra, hogy másképp kell kezelned a hibát. A legtöbb esetben nem szabad a különböző típusú kivételeket azonos módon kezelni.
Ez alól a ritka kivétel a tesztkód és a legfelső szintű kód, ahol mindenféle hibát el akarsz kapni (hogy megakadályozd, hogy megjelenjenek a felhasználói felületen, vagy hogy egy kötegelt feladatot fenntarts). Ezekben az esetekben az általános Exception
(vagy Throwable
) elkaphatja, és megfelelően kezelheti a hibát. Gondolja meg azonban alaposan, mielőtt ezt teszi, és tegyen megjegyzéseket, amelyekben megmagyarázza, miért biztonságos ez ebben a kontextusban.
Alternatívák az általános kivételek fogására:
- Minden egyes kivételt külön-külön fogjon el egy multi-catch blokk részeként, például:
try { ...} catch (ClassNotFoundException | NoSuchMethodException e) { ...}
- Refaktorálja a kódot, hogy finomabb hibakezelést alkalmazzon, több try blokkal. Válassza szét az IO-t az elemzéstől, és kezelje a hibákat minden esetben külön-külön.
- Dobja vissza a kivételt. Sokszor amúgy sem kell ezen a szinten elkapni a kivételt, csak hagyd, hogy a metódus eldobja.
Ne feledje, hogy a kivételek a barátai! Amikor a fordító panaszkodik, hogy nem fogsz el egy kivételt, ne fintorogj. Mosolyogj! A fordító épp most könnyítette meg, hogy futásidejű problémákat kapj el a kódodban.
Ne használj finalizátorokat
A finalizátorok egy módja annak, hogy egy kódrészletet végre lehessen hajtani, amikor egy objektum szemétgyűjtésre kerül. Bár a finalizátorok hasznosak lehetnek a takarításhoz (különösen a külső erőforrások esetében), nincs garancia arra, hogy a finalizátor mikor lesz meghívva (vagy hogy egyáltalán meg lesz-e hívva).
Az Android nem használ finalizátorokat. A legtöbb esetben helyette jó kivételkezelést használhatunk. If you absolutely need a finalizer, define a close()
method (or the like) and document exactly when that method needs to be called (see InputStream for an example). In this case, it’s appropriate but not required to print a short log message from the finalizer, as long as it’s not expected to flood the logs.
Fully qualify imports
When you want to use class Bar
from package foo
, there are two possible ways to import it:
-
import foo.*;
Potentially reduces the number of import statements.
-
import foo.Bar;
Makes it obvious what classes are used and the code is more readable for maintainers.
Use import foo.Bar;
for importing all Android code. An explicit exception is made for Java standard libraries (java.util.*
java.io.*
, etc.) and unit test code (junit.framework.*
).
Java könyvtári szabályok
Vannak konvenciók az Android Java könyvtárak és eszközök használatára. Néhány esetben a konvenció fontos módon megváltozott, és a régebbi kódok elavult mintát vagy könyvtárat használhatnak. Ha ilyen kóddal dolgozunk, nyugodtan folytassuk a meglévő stílust. Új komponensek létrehozásakor azonban soha ne használjon elavult könyvtárakat.
Java stílusszabályok
Minden fájl elején egy szerzői jogi nyilatkozatnak kell állnia, ezt követik a package és import utasítások (minden blokkot egy üres sorral elválasztva), végül pedig az osztály vagy interfész deklarációja. A Javadoc-kommentárokban írja le, hogy mit csinál az osztály vagy az interfész.
/* * Copyright 2020 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 { ...}
Minden osztály és nem triviális nyilvános metódus, amelyet ír, tartalmaznia kell egy Javadoc-kommentárt, amely legalább egy mondatban leírja, hogy mit csinál az osztály vagy a metódus. Ennek a mondatnak harmadik személyű leíró igével kell kezdődnie.
Példák
/** Returns the correctly rounded positive square root of a double value. */static double sqrt(double a) { ...}
vagy
/** * Constructs a new String by converting the specified array of * bytes using the platform's default character encoding. */public String(byte bytes) { ...}
Nem kell Javadocot írnod a triviális get és set metódusokhoz, mint például a setFoo()
, ha a Javadoc csak annyit mondana, hogy “sets Foo”. Ha a metódus valami összetettebbet csinál (például kényszerít egy korlátozást, vagy van egy fontos mellékhatása), akkor dokumentálnod kell. Ha nem nyilvánvaló, hogy a “Foo” tulajdonság mit jelent, akkor dokumentálnod kell.
Minden megírt metódusnak, legyen az nyilvános vagy más, jót tenne a Javadoc. A nyilvános metódusok egy API részét képezik, és ezért Javadocot igényelnek. Az Android nem kényszerít ki konkrét stílust a Javadoc kommentek írására, de érdemes követni a How to Write Doc Comments for the Javadoc Tool című fejezetben található utasításokat.
Rövid módszereket írjon
Ha megvalósítható, tartsa a módszereket kicsiben és koncentráltan. Elismerjük, hogy a hosszú metódusok néha helyénvalóak, ezért nincs kemény korlát a metódusok hosszára vonatkozóan. Ha egy metódus meghaladja a 40 vagy annál több sort, gondolja át, hogy fel lehet-e bontani anélkül, hogy a program szerkezete sérülne.
Mezők definiálása a szokásos helyeken
A mezőket vagy a fájl elején, vagy közvetlenül az őket használó metódusok előtt definiáljuk.
Változók hatókörének korlátozása
Tartsa minimálisra a helyi változók hatókörét. Ez növeli a kód olvashatóságát és karbantarthatóságát, és csökkenti a hibázás valószínűségét. Deklaráljon minden változót a legbelső blokkban, amely a változó minden használatát magában foglalja.
A helyi változókat azon a ponton deklarálja, ahol először használják őket. Szinte minden helyi változó deklarációjának tartalmaznia kell egy inicializálót. Ha még nincs elég információnk egy változó értelmes inicializálásához, halasszuk el a deklarációt addig, amíg ez megtörténik.
Kivételt képeznek a try-catch utasítások. Ha egy változót olyan metódus visszatérési értékével inicializálunk, amely ellenőrzött kivételt dob, akkor azt egy try blokkban kell inicializálni. If the value must be used outside of the try block, then it must be declared before the try block, where it can’t yet be sensibly initialized:
// Instantiate class cl, which represents some sort of SetSet 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 sets.addAll(Arrays.asList(args));
However, you can even avoid this case by encapsulating the try-catch block in a method:
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 setSet s = createSet(cl);s.addAll(Arrays.asList(args));
Declare loop variables in the for statement itself unless there’s a compelling reason to do otherwise:
for (int i = 0; i < n; i++) { doSomething(i);}
and
for (Iterator i = c.iterator(); i.hasNext(); ) { doSomethingElse(i.next());}
Order import statements
The ordering of import statements is:
- Android imports
- Imports from third parties (
com
junit
net
org
) -
java
andjavax
To exactly match the IDE settings, the imports should be:
- Az egyes csoportosításokon belül betűrendben, nagybetűkkel a kisbetűk előtt (például Z az a előtt)
- Az egyes nagyobb csoportosítások között üres sorral elválasztva (
android
com
junit
net
org
java
javax
).
Eredetileg nem volt stíluskövetelmény a sorrendre vonatkozóan, ami azt jelentette, hogy az IDE-k vagy folyamatosan változtatták a sorrendet, vagy az IDE fejlesztőknek kellett kikapcsolniuk az automatikus importkezelési funkciókat és kézzel karbantartaniuk az importokat. Ezt rossznak tartották. Amikor Java-stílust kértek, az előnyben részesített stílusok nagyon eltérőek voltak, és az Androidnak egyszerűen “választania kellett egy sorrendet, és következetesnek kellett lennie”. Ezért választottunk egy stílust, frissítettük a stílus útmutatót, és rávettük az IDE-ket, hogy engedelmeskedjenek neki. Arra számítunk, hogy ahogy az IDE-felhasználók dolgoznak a kódon, az összes csomagban az importok ennek a mintának fognak megfelelni különösebb mérnöki erőfeszítés nélkül.
We chose this style such that:
- The imports that people want to look at first tend to be at the top (
android
). - The imports that people want to look at least tend to be at the bottom (
java
). - Humans can easily follow the style.
- IDEs can follow the style.
Put static imports above all the other imports ordered the same way as regular imports.
Use spaces for indentation
We use four (4) space indents for blocks and never tabs. When in doubt, be consistent with the surrounding code.
We use eight (8) space indents for line wraps, including function calls and assignments.
Recommended
Instrument i = someLongExpression(that, wouldNotFit, on, one, line);
Not recommended
Instrument i = someLongExpression(that, wouldNotFit, on, one, line);
Follow field naming conventions
- Non-public, non-static field names start with
m
. - Static field names start with
s
. - Other fields start with a lower case letter.
- Public static final fields (constants) are
ALL_CAPS_WITH_UNDERSCORES
.
For example:
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 standard brace style
Put braces on the same line as the code before them, not on their own line:
class MyClass { int func() { if (something) { // ... } else if (somethingElse) { // ... } else { // ... } }}
We require braces around the statements for a conditional. Exception: If the entire conditional (the condition and the body) fit on one line, you may (but are not obligated to) put it all on one line. For example, this is acceptable:
if (condition) { body();}
and this is acceptable:
if (condition) body();
but this is not acceptable:
if (condition) body(); // bad!
Limit line length
Each line of text in your code should be at most 100 characters long. While much discussion has surrounded this rule, the decision remains that 100 characters is the maximum with the following exceptions:
- Ha egy megjegyzéssor 100 karakternél hosszabb példaparancsot vagy szó szerinti URL-címet tartalmaz, az a sor a könnyebb kivágás és beillesztés érdekében lehet hosszabb 100 karakternél.
- Az import sorok túlléphetik a korlátot, mert az emberek ritkán látják őket (ez is egyszerűsíti az eszközírást).
Szokásos Java megjegyzések használata
A megjegyzéseknek meg kell előznie az azonos nyelvi elemhez tartozó egyéb módosítókat. Az egyszerű jelölő megjegyzések (például @Override
) a nyelvi elemmel egy sorban szerepelhetnek. Ha több megjegyzés vagy paraméterezett megjegyzés van, soronként egyenként, ábécé sorrendben kell felsorolni őket.
Az Android szabványos gyakorlata a három előre definiált megjegyzésekre vonatkozóan a Java-ban a következő:
- Használja a
@Deprecated
annotációt minden olyan esetben, amikor az annotált elem használata nem javasolt. Ha a@Deprecated
annotációt használja, akkor rendelkeznie kell egy@deprecated
Javadoc taggel is, és annak meg kell neveznie egy alternatív implementációt. Emellett ne feledje, hogy egy@Deprecated
metódusnak még működnie kell. Ha olyan régi kódot lát, amely@deprecated
Javadoc taggel rendelkezik, adja hozzá a@Deprecated
megjegyzést. - Használja a
@Override
annotációt, amikor egy metódus felülírja egy szuperosztály deklarációját vagy implementációját. Ha például a@inheritdocs
Javadoc taget használja, és egy osztályból (nem interfészből) származtatja, akkor azt is meg kell jegyzetelnie, hogy a metódus felülbírálja a szülőosztály metódusát. - A
@SuppressWarnings
megjegyzést csak olyan körülmények között használja, amikor lehetetlen kiküszöbölni a figyelmeztetést. If a warning passes this “impossible to eliminate” test, the@SuppressWarnings
annotation must be used, to ensure that all warnings reflect actual problems in the code.When a
@SuppressWarnings
annotation is necessary, it must be prefixed with aTODO
comment that explains the “impossible to eliminate” condition. This normally identifies an offending class that has an awkward interface. Például:// TODO: The third-party class com.third.useful.Utility.rotate() needs generics@SuppressWarnings("generic-cast")List<String> blix = Utility.rotate(blax);
When a
@SuppressWarnings
annotation is required, refactor the code to isolate the software elements where the annotation applies.
Treat acronyms as words
Treat acronyms and abbreviations as words in naming variables, methods, and classes to make names more readable:
Good | Bad |
---|---|
XmlHttpRequest | XMLHTTPRequest |
getCustomerId | getCustomerID |
class Html | class HTML |
String url | String URL |
long id | long ID |
As both the JDK and the Android code bases are inconsistent around acronyms, it’s virtually impossible to be consistent with the surrounding code. Therefore, always treat acronyms as words.
Use TODO
comments for code that is temporary, a short-term solution, or good enough but not perfect. These comments should include the string TODO
in all caps, followed by a colon:
// TODO: Remove this code after the UrlTable2 has been checked in.
és
// TODO: Change this to use a flag instead of a constant.
Ha a TODO
a “Egy későbbi időpontban csinálj valamit” formájú, győződj meg róla, hogy vagy egy konkrét dátumot (“2005 novemberéig javítsd ki”) vagy egy konkrét eseményt (“Távolítsd el ezt a kódot, miután minden gyártósori keverő megértette a V7-es protokollt.”) tartalmaz.
Takarékosan naplózzunk
Bár a naplózás szükséges, negatív hatással van a teljesítményre, és elveszti a hasznosságát, ha nem tartjuk ésszerűen tömörnek. A naplózási lehetőségek öt különböző szintű naplózást biztosítanak:
-
ERROR
: Akkor használjuk, ha valami végzetes dolog történt, azaz valami, aminek a felhasználó számára látható következményei lesznek, és nem állítható helyre bizonyos adatok törlése, alkalmazások eltávolítása, az adatpartíciók törlése vagy az egész eszköz újraflashelése (vagy még rosszabb) nélkül. Ez a szint mindig naplózásra kerül. Azok a problémák, amelyek aERROR
szintjén indokolják a naplózást, jó jelöltek arra, hogy jelentsenek egy statisztikákat gyűjtő szervernek. -
WARNING
: Akkor használjuk, ha valami komoly és váratlan dolog történt, vagyis olyasmi, aminek a felhasználó számára látható következményei lesznek, de valószínűleg adatvesztés nélkül helyreállítható valamilyen explicit művelet végrehajtásával, a várakozástól vagy egy alkalmazás újraindításától kezdve egészen egy alkalmazás új verziójának újratöltéséig vagy a készülék újraindításáig. Ez a szint mindig naplózásra kerül. AWARNING
szintű naplózást indokoló problémák szintén megfontolhatók a statisztikákat gyűjtő kiszolgálónak történő jelentésre. -
INFORMATIVE
: Arra használjuk, hogy megjegyezzük, hogy valami érdekes történt, vagyis amikor olyan helyzetet észlelünk, amelynek valószínűleg széleskörű hatása van, bár nem feltétlenül hiba. Az ilyen állapotot csak olyan modulnak kell naplóznia, amely úgy véli, hogy az adott tartományban ő a leghitelesebb (a nem hiteles komponensek általi kettős naplózás elkerülése érdekében). Ez a szint mindig naplózásra kerül. -
DEBUG
: Használja a váratlan viselkedések kivizsgálásához és hibakereséséhez szükséges további megjegyzésekhez, hogy mi történik az eszközön, ami fontos lehet a váratlan viselkedések kivizsgálásához és hibakereséséhez. Csak annyit naplózzon, amennyi szükséges ahhoz, hogy elegendő információt gyűjtsön arról, hogy mi történik a komponenssel. Ha a hibakeresési naplók dominálnak a naplóban, akkor érdemes a verbose naplózást használni.Ez a szint még a release buildeknél is naplózásra kerül, és egy
if (LOCAL_LOG)
vagyif LOCAL_LOGD)
blokkal kell körülvenni, ahol aLOCAL_LOG
az osztályodban vagy alkomponensedben van definiálva, így lehetőség van minden ilyen naplózás kikapcsolására. Ezért aif (LOCAL_LOG)
blokkban nem lehet aktív logika. A naplózáshoz szükséges összes karakterlánc-építést szintén aif (LOCAL_LOG)
blokkban kell elhelyezni. Ne alakítsuk át a naplózás hívását metódushívássá, ha ez azt eredményezi, hogy a karakterlánc felépítése aif (LOCAL_LOG)
blokkon kívül történik.Van olyan kód, amelyben még mindig
if (localLOGV)
szerepel. Ez is elfogadhatónak tekinthető, bár a név nem szabványos. -
VERBOSE
: Minden másra használja. Ez a szint csak debug buildeknél kerül naplózásra, és egyif (LOCAL_LOGV)
blokkal (vagy azzal egyenértékűvel) kell körülvenni, hogy alapértelmezés szerint ki lehessen fordítani. A kiadásos buildeknél minden sztringépítés ki lesz szedve, és aif (LOCAL_LOGV)
blokkban kell megjelennie.
Jegyzetek
- Egy adott modulon belül, a
VERBOSE
szinten kívül, egy hibát lehetőleg csak egyszer kell jelenteni. Egy modulon belüli egyetlen függvényhívásláncon belül csak a legbelső függvény adja vissza a hibát, és az ugyanabban a modulban lévő hívók csak akkor adjanak hozzá némi naplózást, ha az jelentősen segít a probléma elkülönítésében. - Egy modulláncon belül, a
VERBOSE
szint kivételével, amikor egy alacsonyabb szintű modul egy magasabb szintű modulból érkező érvénytelen adatot észlel, az alacsonyabb szintű modul csak akkor naplózza ezt a helyzetet aDEBUG
naplóba, és csak akkor, ha a naplózás olyan információval szolgál, amely egyébként nem áll a hívó rendelkezésére. Különösen nincs szükség olyan helyzetek naplózására, amikor egy kivételt dobnak (a kivételnek minden releváns információt tartalmaznia kell), vagy amikor az egyetlen naplózott információ egy hibakódban van. Ez különösen fontos a keretrendszer és az alkalmazások közötti interakcióban, és a keretrendszer által megfelelően kezelt, harmadik féltől származó alkalmazások által okozott állapotoknak nem szabad aDEBUG
szintnél magasabb szintű naplózást kiváltaniuk. Az egyetlen helyzet, amelynek aINFORMATIVE
szinten vagy annál magasabb szinten kell naplózást kiváltania, az az, amikor egy modul vagy alkalmazás hibát észlel a saját szintjén vagy egy alacsonyabb szintről érkező hibát. - Ha egy olyan állapot, amely normális esetben némi naplózást indokolna, valószínűleg sokszor fordul elő, jó ötlet lehet valamilyen sebességkorlátozó mechanizmus implementálása, hogy megakadályozzuk a naplók túlcsordulását ugyanazon (vagy nagyon hasonló) információ sok duplikált példányával.
- A hálózati kapcsolat elvesztése általánosnak tekinthető és teljes mértékben várható, és nem kell indokolatlanul naplózni. A hálózati kapcsolat elvesztését, amelynek következményei vannak egy alkalmazáson belül, a
DEBUG
vagyVERBOSE
szinten kell naplózni (attól függően, hogy a következmények elég súlyosak és váratlanok-e ahhoz, hogy egy release buildben naplózzák). - A teljes fájlrendszert egy olyan fájlrendszeren, amely harmadik féltől származó alkalmazások számára vagy nevében elérhető, nem szabad INFORMÁCIÓS szintnél magasabb szinten naplózni.
- Bármilyen nem megbízható forrásból érkező érvénytelen adat (beleértve a megosztott tárhelyen lévő fájlokat vagy a hálózati kapcsolaton keresztül érkező adatokat) elvártnak tekintendő, és nem szabadna a
DEBUG
-nél magasabb szintű naplózást kiváltani, ha érvénytelennek észlelik (és még akkor is a naplózásnak a lehető legkorlátozottabbnak kell lennie). -
String
objektumokra használva a+
operátor implicit módon létrehoz egyStringBuilder
példányt az alapértelmezett puffermérettel (16 karakter) és potenciálisan más ideiglenesString
objektumokkal. Tehát aStringBuilder
objektumok explicit létrehozása nem drágább, mint az alapértelmezett+
operátorra hagyatkozni (és sokkal hatékonyabb lehet). Ne feledje, hogy a -t hívó kódot a kiadási buildeknél lefordítják és végrehajtják, beleértve a karakterláncok építését is, még akkor is, ha a naplók nem kerülnek beolvasásra. - Minden olyan naplózásnak, amelyet arra szántak, hogy mások is olvassák, és elérhető legyen a release buildekben, tömörnek kell lennie anélkül, hogy rejtélyes lenne, és érthetőnek kell lennie. Ez magában foglalja az összes naplózást a
DEBUG
szintig. - Ha lehetséges, tartsuk a naplózást egyetlen sorban. Akár 80 vagy 100 karakter hosszúságú sorok is elfogadhatók. Lehetőség szerint kerülje a 130 vagy 160 karakternél (a címke hosszával együtt) hosszabb sorokat.
- Ha a naplózás sikereket jelent, soha ne használja a
VERBOSE
-nél magasabb szinteken. - Ha az ideiglenes naplózást egy nehezen reprodukálható probléma diagnosztizálására használja, tartsa a
DEBUG
vagyVERBOSE
szinten, és zárja be if blokkokkal, amelyek lehetővé teszik a letiltását fordítási időben. - Legyen óvatos a biztonsági szivárgásokkal a naplón keresztül. Kerülje a személyes információk naplózását. Különösen kerülje a védett tartalomra vonatkozó információk naplózását. Ez különösen fontos a keretrendszer kódjának írásakor, mivel nem könnyű előre tudni, hogy mi lesz és mi nem lesz privát információ vagy védett tartalom.
- Soha ne használjon
System.out.println()
(vagyprintf()
natív kód esetén). ASystem.out
és aSystem.err
átirányításra kerül a/dev/null
-be, így a nyomtatási utasításoknak nincs látható hatása. Azonban az összes karakterlánc-építés, ami ezeknél a hívásoknál történik, továbbra is végrehajtásra kerül. - A naplózás aranyszabálya, hogy a te naplóid nem nyomhatnak ki szükségtelenül más naplókat a pufferből, ahogyan mások sem nyomhatják ki a tieidet.
Javatests stílusszabályok
Kövesd a tesztmódszerek elnevezési konvenciókat, és használj aláhúzást, hogy elválassza a tesztelés tárgyát a tesztelt konkrét esettől. Ez a stílus megkönnyíti a tesztelt esetek áttekinthetőségét. For example:
testMethod_specificCase1 testMethod_specificCase2void testIsDistinguishable_protanopia() { ColorMatcher colorMatcher = new ColorMatcher(PROTANOPIA) assertFalse(colorMatcher.isDistinguishable(Color.RED, Color.BLACK)) assertTrue(colorMatcher.isDistinguishable(Color.X, Color.Y))}