A TIOBE Java kódolási szabályokról

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.

Szólj hozzá!