Jos olet epävarma jostain tyyliseikasta, katso mallia standardikirjastoista. Niiden ainakin tulisi olla hyviä esimerkkejä myös tyylillisesti. Älä kuitenkaan katso mallia ominaisuuksista joissa on merkki "Deprecated". Ne ovat epäyhtenäisen tyylin tai muun vastaavan takia poistumassa olevia ominaisuuksia ja siis usein esimerkkejä vanhasta tyylistä.
| Mihin tyyliin ikinä päädytkin, pysy siinä johdonmukaisesti ainakin läpi koko moduulin. |
Esimerkki:
/* Esimerkkiohjelma. *
* Ohjelmoinut Jari Juslin 1998. *
* Jari.Juslin@iki.fi */
/** Malliluokka
* @author Jari Juslin
*/
class Luokka {
}
|
Ei ole lainkaan huono idea tehdä jokaisen tiedoston alkuun tunnistelohkoa josta käy ilmi tiedoston tekijä ja summittainen ajankohta ja ohjelman tarkoitus, ehkä jopa yhteystietoja. Näiden merkintöjen merkitys korostuu varsinkin siinä vaiheessa kun koodisi on osa laajempaa kokonaisuutta tai laitat sen julkisesti saataville, vaikkapa veppiin.
Java-koodia kirjoittaessasi, laita jokainen luokka omaan tiedostoonsa. Ei-julkiset luokat on mahdollista kirjoittaa tiedostoihin jotka eivät ole nimettyjä niiden itsensä mukaan, mutta kaikki mikä on mahdollista ei ole suositeltavaa. Omien kokemuksieni mukaan aiheuttaa paljon sekaannusta ja kovin vähän hyötyä jos luokka ei löydy omaa nimeään kantavasta tiedostosta, tai toisaalta, kahden luokan koodit sekoittuvat toisiinsa samassa tiedostossa.
Esimerkki:
class Luokka {
public void metodi() {
int i = 0,
j = 1;
if (i == 0) {
while (i < 30) {
i++;
}
}
if (i == j)
suoritaJotain();
for (j=0; j < i; j++)
;
}
}
|
Sisennä jokainen alilohko edellisestä. Sisennä mieluiten joko 2, hyvällä syyllä 4 merkkiä.
Käytä sisentäessäsi joko tabulaattoria tai välilyöntejä, ei sekaisin. Tabulaattorin aiheuttama sisennys vaihtelee, joten molempien käyttäminen sekaisin johtaa ennemmin tai myöhemmin koodin näkymiseen sekasotkuna.
Laita lohkon aloittava aaltosulku lohkon aloituksen määräävälle riville. Jos olet tottunut laittamaan seuraavalle riville yksinään, sekin käy. Jos teet valintalauseen ilman lohko-osaa, laita suoritusosa seuraavalle riville sisennettynä. Jos suoritusosa on tyhjä, laita puolipiste seuraavalle riville sisennettynä.
Mikäli mahdollista, sisennä muuttujien esittelyt siten että muuttujien nimet ovat samalla tasalla, se helpottaa lukemista.
Mikäli ei ole erityistä syytä muuhun, suorita toiminta suoritusosassa, ei valintalauseessa ja laita jokaisen valintalauseen suoritusosa aaltosulkuihin.
Esimerkki:
public class MunLuokka {
final static int MAX_ARVO = 30;
double arvo;
public MunLuokka(double arvo) {
this.arvo = arvo;
}
MunLuokka munLuokka = new MunLuokka();
public void luvunLasku() {
int i = 0;
if (i == 0) {
while (i < MAX_ARVO) {
i++;
}
}
}
}
|
Nimeä johdonmukaisesti. Oletuksena kaikki kirjoitetaan pienillä kirjaimilla.
Luokkien nimet alkavat aina isolla, samoin luokan nimen eri osat. Ilmentymien nimet alkavat pienellä, mutta eri osat taas isolla. Usein ilmentymän nimi on sama kuin luokan, vain nimi pienellä alkukirjaimella.
Metodien nimet alkavat aina pienellä alkukirjaimella, isolla nimen osien alkukirjaimet.
Perustyyppien muuttujat aina pienellä alkukirjaimella.
Vakiot kirjoitetaan kokonaan isoilla kirjaimilla.
Luokkamuuttujat kirjoitetaan kuten ilmentymän muuttujat, mutta niihin viitataan käyttäen luokan nimeä.
Mikäli metodin tai konstruktorin parametri on sisältää samantyyppistä tietoa kuin ilmentymämuuttuja, jonka arvoksi se tullaan sijoittamaan, on tapana nimenä metodin patametri saman nimiseksi. Tällöin ilmentymän muuttujaan viitataan määreellä "this.".
Esimerkki:
class Luokka {
int arvo = 0;
/** Palauttaa luokan arvon. **/
public int annaArvo() {
return arvo;
}
/** Asettaa luokan arvon. **/
public void asetaArvo(int arvo) {
if (this.arvo == 0 && arvo != 0) {
this.arvo = arvo;
}
}
}
tai
class MyClass {
int value = 0;
/** Returns value of the class. **/
public int getValue() {
return value;
}
}
|
Käytä kielenä joko suomea tai englantia, mutta vain jompaa kumpaa. Kirjoita kaikki luokkien, metodien ja muuttujien nimet sillä kielellä, samoin kommentit ja dokumenttikommentit. Oleellista on, että lukijakunta saa parhaan hyödyn irti nimistöstäsi ja kommenteistasi.
Mikäli englantisi on erinomaista ja koodiasi pitäisi ehkä joskus lukea jonkun ulkomaalaisen, käytä englantia.
Mikäli saat ilmaistua asiat selkeämmin ja täsmällisemmin suomen kielellä, ja on epätodennäkäistä että koodiasi pitäisi ymmärtää ulkomaalaisen, kirjoita suomeksi.
Mikäli sinusta tuntuu luontevammalta käyttää metodien ja atribuuttien nimissä skandinaavisia kirjaimia, eli "ääkkösiä", käytä niitä. Luokkien nimissä ei skandinaavisia merkkejä kuitenkaan ole syytä käyttää. Luokat tallennetaan luokan nimen mukaiseen tiedostoon, ja kaikki järjestelmät eivät osaa käsitellä oikein tiedostoja joissa on ääkkösiä.
Älä käytä nimissä sekaisin ääkkösellisiä ja ääkkösettömiä muotoja sekaisin. "annaVäli" ja "asetaVali" ovat kumpikin kelvollisia nimiä, mutta jos ne olisivat samassa luokkakokonaisuudessa, sekaantumisia tulisi varmasti. Yhtenäinen tyyli selkeyttää koodia ja helpottaa sen lukemista ja luokkien käyttöä.
Nimeä loogisesti ja selittävästi. Esimerkiksi arvoja asettavat metodit nimetään englanniksi setValue() ja arvoja hakevat getValue(). Suomeksi annaArvo() ja asetaArvo(). Tutustu ainakin lyhyesti Javan standardikirjastojen nimeämiskäytäntöön. Pyri siihen että luokan käyttäjä osaa arvata nimen ilman dokumenttiäkin jos tietää mitä se tekee.
Konstruktorien ja asettavien metodien uutta arvoa osoittava muuttuja on mahdollista ja järkevää nimetä samalle nimelle, jolloin ilmentymän muuttujaan viitataan määreellä this.muuttuja. Samaan tarkoitukseen käytettävää arvoa sisältävä muuttuja, siis sama nimi.
Esimerkki:
/** Tämä luokka toimii
esimerkkinä pakkauksesta. **/
package jari.esim;
import fi.cgs.ohjelma.apu.*;
class Luokka {
}
|
Pakkauksen nimet kirjoitetaan pienellä, ja niiden osat pyritään pitämään lyhyinä. Pakkauksen nimen ensimmäinen taso kertoo pakkauksen laatijan, joka esimerkissä on yksinkertaisesti "jari".
Luokan käyttämä toinen pakkaus sen sijaan on tehty töissä, joten siinä "laatijan" nimenä on ko. pakkauksen alaisuuteen luokkia kehittävä yritys, esimerkissä "fi.cgs".
Nykyisin Sun suosittaa käyttämään pakkauksen nimeä muodossa "maa.domain", eli esimerkissä käyttöön otettu pakkaus olisi siis domainin cgs.fi alla esiintyvä yritys. Tällä pyritään Internetin laajuisesti yksikäsitteisiin nimiin. Jos organisaatiolla tai henkilöllä jonka nimiin koodaat ei ole omaa domainia, joudut tietysti valitsemaan jollain muulla periaatteella.
Ellei mitään erityistä syytä muuhun ole (laiskuus ei ole erityinen syy :-), sijoita aina kaikki ohjelmasti johonkin pakkaukseen. Ellei muuta, niin ainakin oman ylätasosi alle johonkin epämääräistä sälää sisältävään pakkaukseen, ts. jokin nimesi.sekalainen. Pakkauksettomat luokat tuottavat ajan kanssa ongelmia, noista ainakin tiedät - ja muut tietävät - että ne ovat sinun tekeleitäsi.
Seuraavat osat määrittelevät hierarkisesti luokkien aseman. Samaan moduuliin, kirjastoon tai kokonaisuuteen liittyvät luokat ovat yleensä samassa pakkauksessa. Isoissa kokonaisuuksissa kannattaa jakaa käyttötarkoituksen ja keskinäisten suhteiden perusteella alipakkauksiin. Esimerkkipätkässä moduuliin "ohjelma" kuuluvat apuluokat on jaoteltu omaan alipakkaukseensa "apu".
Moduulien nimeämisessä ja jaottelussa, kuten lähes kaikissa muissakin tämän sivun kohdissa, kannattaa katsoa mallia Javan standardikirjastoista.
Esimerkki:
/** Tämä luokka toimii
esimerkkinä kommentoinnista. **/
class Luokka {
/** Asettaa luokan arvon. Asettaa
uuden arvon, jos arvoa ei ole
aiemmin asetettu ja uusi
<TT>arvo</TT> poikkeaa nollasta **/
public void asetaArvo(int arvo) {
if (this.arvo == 0 && arvo != 0) {
this.arvo = arvo;
}
}
}
|
Kirjoita jokaiselle luokalle ja metodille dokumenttikommentti, joka kertoo luokan tai metodin koko oleellisen toiminnan pääpiirteittäin. Dokumenttikommentin ensimmäinen virke tulee javadoc:illa tehtyyn sisällysluetteloon ja koko kommentti tarkempaan selostukseen.
Dokumenttikommentissa voi ja kannattaa käyttää html-merkintää, mikäli sillä saadaan asia selkeämmin esille. Käytä kuitenkin varoen esim. lihavointia äläkä käytä tekstikoon muutoksia ilman syytä, muuten tuloksena tulevasta dokumentista tulee liian hajanainen ja poikkeava. Koodinpätkät ja muuttujien nimet on järkevää laittaa <TT> ja </TT> -merkkien väliin.
Kommentoi lisäksi kaikki vähänkään epäselvät muuttujat, ja kaikki metodit joiden toiminta ei ole ilmi selvää. Yli 15 riviset metodit eivät koskaan ole itsestään selviä. Yli kaksi sisäkkäistä lohkoa sisältävät rakenteet eivät koskaan ole itsestään selviä.
Kirjoita esille ainakin käyttämäsi algoritmin nimi, mielellään lyhyt selvitys myös. Koodin ja dokumentin pitää kummankin tehdä toiminta selväksi yksinään.
Esimerkki:
/** Tämä luokka toimii
esimerkkinä metodien
erottimesta. **/
class Luokka {
int arvo;
/* ************************ */
public void asetaArvo(int arvo) {
this.arvo = arvo;
}
/* ************************ */
public int annaArvo() {
return arvo;
}
}
|
Luokkien lähdekooditiedostot kasvavat nopeasti suhteellisen pitkiksi, lähes aina pidemmiksi kuin mitä kerralla ruudulla saa näkymään.
Jotta luokan eri osat erottuisivat selkeämmin, monet käyttävät luokan attribuuttien esittelyn ja metodien väleissä eräänlaista väliviivaa, joka on muodostettu kommenttimerkinnällä. Javassa kannattaa käyttää välilyöntiä päissä, sillä tällöin mikään ohjelma ei luule erotinta dokumenttikommentiksi.
Toinen hyvä väline metodien ja eri osien erotteluun on yksinkertaisesti tyhjät rivit. Kuten erimerkissä näkyy, erottimien molemmin puolin on tyhjä rivi. Tyhjiä rivejä saa, ja kannattaa käyttää myös metodien ja esittelyosien sisällä käyttää tyhjiä rivejä erottamaan eri kokonaisuudet.
Tyhjä tila lähdekoodissa ei ole kustannus, sitä ei kannata säästää. Liika tietysti on aina liikaa, niin kaikessa.
Esimerkki:
/** Tämä luokka toimii
esimerkkinä for-luupin
kierroslaskurista. **/
class Luokka {
/* ************************ */
public void metodi() {
for (int i=0; i < 10; i++) {
for (int j=10; j > 0; j--) {
System.out.println(
"(" + i + ", " + j + ")");
}
}
}
}
|
Älä käytä yksikirjaimisia muuttujien nimiä. Senhän jo tiesitkin. Poikkeus kuitenkin vahvistaa säännön. Ohjelmoijien kirjoittamaton sääntö jo aikakausia on ollut, että for-luupissa muuttujan nimi voi olla yksikirjaiminen. Tällöin käytetään kirjaimia i, j jne. i lienee lyhenne sanasta index.
Sama toimii tietysti toisinkin päin. Älä käytä muiden muuttujien nimenä i:tä tai j:tä, sillä niiden oletetaan ilman muuta olevan toistolauseen kierroslaskureita.
Ei-julkisia samaan pakkaukseen kuuluvia luokkia voi sijoittaa useamman samaan lähdekooditiedostoon. Älä tee näin ilman hyvää syytä. Kun luokan lähdekoodi on omaa nimeään kantavassa tiedostossa, sen löytää. Jos ei ole, sitä ei löydä.
Kaikkea mikä on mahdollista ei pidä tehdä.