A TIOBE Java Coding Standard aktuális verziója a 3.10. Java programozási nyelven írt/karbantartott forráskódra vonatkozó szabályokat/ajánlásokat tartalmaz. Célja: a kódolási hibák elkerülése, az elavult vagy implementációfüggő nyelvi funkciók használatának elkerülése, illetve a következetes, konzisztens kódolási stílus kialakítása.
A TIOBE Java Coding Standard dokumentáció szerkezete
A TIOBE Java kódolási szabályok 19 kategóriába soroltak, 1-8-ig szint alapján csoportosítottak, továbbá ellenőrzött és nem ellenőrzött állapotban vannak. Az alábbi Sankey-diagram segít áttekinteni a dokumentációt:
A TIOBE Java kódolási szabályok kategóriánként
A továbbiakban néhány kategóriából emeltem ki néhány szabályt/ajánlást – amiket fontosabbnak tartok.
- 34 db alapszabály van. Ezek olyan jó gyakorlatok, amiket mindenkinek követnie kell. Nem írunk üres
if,
switchutasításokat. Nem írunk üres
while,
try,
finally,
synchronized,
static blokkokat. Nem írunk tesztelős ciklust számlálósként, így:
for (;true;). Nem módosítjuk a
for ciklus változóját a ciklusmagban. Ne használjunk felesleges
public,
static,
finalmódosítókat és (eljárásokban)
return utasítást.
- 8 db kódmérethez kötődő szabály van. Ne írjunk hosszú, sok utasításból álló metódusokat. Ne használjunk túl sok paramétert metódusok, konstruktorok esetén. Ügyeljünk a forráskód ciklomatikus komplexitására, amely a tesztelési nehézségek egyik mutatószáma. Ne tervezzünk túl sok publikus metódust és mezőt/tulajdonságot egy osztályba. A limitek a fentiek sorrendjében: 100 utasítás, 10 paraméter, 1000 kódsor, 10-es komplexitású metódus, 45 metódus, 15 mező/tulajdonság.
- 4 db kommentekre vonatkozó szabály van. Ezek forrásfájlokra, annotációkra, TODO-kra és speciális JavaDoc-ra érvényesek.
- 4 db ellentmondásos/vitatott szabály van. Például ne importáljunk a
sun.* csomagokat, illetve ne használjunk felesleges kerek zárójelpárokat, értékadással egybeépített összehasonlítást egy feltételben.
- 42 db tervezési szabály van. Függvényben lévő
if-then-else utasításben lévő két
return helyett adjuk vissza közvetlenül a logikai kifejezés értékét. Logikai kifejezésekben ne legyenek felesleges összehasonlítások. A
switch utasításban hiányzó
break utasítás tervezési hibára utal (bár nem szintaktikai követelmény, hogy legyen). A
switch utasításban kellene
default ágnak lennie (és egyben álljon az utolsó helyen). Ne definiáljuk felül egy metódus bejövő paraméterét. Az
equals() összehasonlító metódust ne hívjuk meg
null paraméterrel. Ne használjunk idempotens műveleteket, például ne adjunk értékül egy változót/objektumot saját magának. A
SimpleDateFormat osztály és
String.toLowerCase()/toUpperCase() metódusok használata során mindig állítsuk be a
Locale objektumot. A
synchronized kulcsszót ne kívülről, metódusra, hanem belülről, blokkban használjuk. Konstanst ne inicializáljunk
null-ként. Kollekciók esetén a
size()==0 vagy
size()!=0 helyett hívjuk meg az
isEmpty() függvényt. Az
instanceof operátor használata előtt nem kell ellenőrizni, hogy az objektum nem
null. A megnyitott erőforrásokat mindig zárjuk le a
close() metódussal.
- 7 db véglegesítéshez kötődő szabály van. Ha írunk
finalize() metódust, akkor az ne legyen üres és ne legyen paramétere sem. Inkább ne írjunk
finalize() metódust, mert nincs garancia arra, hogy végrehajtódik (illetve szintén nem tudjuk, hogy mikor fut le).
- 5 db importáláshoz kapcsolódó szabály van. Importáljunk pontosan. Ne importáljunk a
java.lang csomagból (mert ez alapértelmezett). Ne importáljunk többszörösen. Ne maradjanak nem használt importok a végleges forráskódban.
- 4 db logolásra vonatkozó szabály van. Egy osztályban egyetlen
Logger legyen. A
System.(out|err).print() metódus és kivételkezelés során
printStackTrace() helyett inkább logoljunk.
- 1 db szabály van a többszálúsághoz kötődően. Példányváltozó közvetlenül elérhető több szál számára. Az ehhez való megosztott hozzáférés szabályozása, szinkronizálása nehéz, ezért inkább hozzunk létre belőle annyi példányt, ahány szálon fut a program.
- 10 db elnevezésre vonatkozó szabály van. Kerüljük a hosszú változóneveket és a rövid metódusneveket. Ne használjunk
$ jelet a változók, metódusok, osztályok, interfészek elnevezése során. Ne használjunk a
Foo osztályban
Foo() metódusnevet (mert ez a konstruktor), és
foo változónevet sem. Minden osztály és interfész tartozzon csomagba.
- 8 db optimizáláshoz kötődő szabály van. Ha egy változó nem módosul és csak egyszer kap értéket, akkor legyen konstans. Ha tömbből generikus listát készítünk, akkor használjuk az
Arrays.asList() metódust (ahelyett, hogy ciklust írunk az adatszerkezet konstrukciójához). Csomagolóosztályt csak szükség esetén alkalmazzunk (mert autoboxing van). A
Calendar helyett használjunk inkább „olcsóbb” osztályokat.
- 2 db kódbiztonsági szabály van. Ne égessünk a forráskódba kriptográfiához kötődő adatokat (kód, jelszó, hash). Ezeket a kulcsokat külső fájlokban tároljuk.
- 11 db szabály vonatkozik a kötelező kivételkezelésre. Nem szabad
catch (Throwable t) ágat használni, mert memóriaproblémát okozhat. Konstruktor/metódus ne dobjon általános kivételt (
Exception) – helyette dobjon szükség esetén speciálisabb/leszármazott kivételt. Ne kapjunk el általános kivételt; specializáljuk ezt is. Kivételkezeléssel ne valósítsunk meg vezérlést. Ne kapjunk el
NullPointerException-t; inkább szüntessük meg a keletkezésének okát. Ha lehet, akkor a
try-catch-finally blokk helyett alkalmazzunk erőforrás-kezelő kivételkezelést.
- 14 db szabály vonatkozik a szövegkezelő
String és
StringBuffer osztályok használatára. Közvetlenül inicializáljuk a
String típusú objektumokat, felesleges hozzá konstruktort használni. Csak akkor használjuk a
toString() metódust, amikor feltételül szükséges. Összehasonlításnál az
equalsIgnoreCase() metódus gyorsabb a
toUpperCase/toLowerCase().equals() metódusoknál. Láncoljuk az
append() függvényeket, amikor csak lehet. Ha nem szükséges, akkor ne használjuk a
String.valueOf() függvényt.
String objektumok összehasonlítát az
equals() metódussal végezzük el.
- 3 db típusrezolúciós szabály van. Használjunk
ArrayList list=new ArrayList() helyett
List list=new ArrayList() deklarációt (értékadás bal oldalán statikus típus (interfész), jobb oldalán dinamikus típus (implementáció)). Tömb létrehozásához használjunk
int[] x=new int[] {1, 2, 3} helyett
int[] x={1, 2, 3} inicializáló blokkot. Generikus lista létrehozásánál használjunk
List<String> strings=new ArrayList<String>() dupla gyémánt operátor helyett csak egyet, így:
List<String> strings=new ArrayList<>().
- 5 db nem használt forráskódokra vonatkozó szabály van. Ezek privát változókra, lokális változókra, privát metódusokra, felesleges értékadásokra, üres utasításokra érvényesek.
Nem tértem ki a 2 db klónozáshoz, 2 db csatoláshoz (importáláshoz), az 1 db stílushoz kötődő szabályra. Továbbá van 5 db már elavult, tervezésre vonatkozó szabály.
A fentieket érdemes megfogadni, betartani, céges környezetben megfelelően kiegészíteni, testre szabni. A teljes angol nyelvű dokumentáció elérhető: Coding Standard Viewer. A weboldalon érdemes a Java programozási nyelvre vonatkozó szabályokat, ajánlásokat összehasonlítani más nyelvekre vonatkozó szabályokkal, ajánlásokkal. Összesen 8 programozási nyelvhez találhatók szabályok, ajánlások. Elérhetők a forráskód minőségét, karbantarthatóságát kifejező TQI szempontok, paraméterek dokumentációi is: TIOBE Quality Indicator (TQI), valamint a TIOBE TÜViT Trusted Product Maintainability ISO/IEC 25010 Quality Model. Egy szint felett már ezeket is figyelembe kell venni.
Korábbi blog bejegyzésünk a fenti saját készítésű ábra, grafikon elkészítéséről: Sankey-diagram készítése. Érdemes a hozzászólásokat is tanulmányozni a jó példákért.