Vaikka ohjelmien kirjoittaminen tuntuukin joskus vaikealta, on ohjelmien lukeminen usein vielä vaikeampaa. Huonosti tehdyn ohjelman toimintaa on miltei mahdoton selvittää. Tämä teksti selittää yleisiä periaatteita siitä, millaista on hyvän tietokoneohjelman lähdekoodi. Kirjoitus ei käsittele mitään erityistä ohjelmointikieltä, vaan tarkoitus on antaa melko yleispäteviä neuvoja. Teksti on suunnattu lähinnä aloittelijoille.
Yleensä ensimmäisenä ohjelmointia opiskelevalle vastaan tuleva asia on
asioiden nimeäminen hyvin.
Muuttujien, funktioiden, luokkien jne. nimien pitää olla kuvaavia.
Kukaan ei ymmärrä mitä a=b*c
tarkoittaa, sen sijaan
verot=tulot*veroprosentti
kertoo heti, mitä ollaan tekemässä.
Älä säästä kirjaimia, satunnaisVaihtelu
on parempi kuin
satVaiht
puhumattakaan nimestä sv
. Kunnollisten
nimien käyttö kannattaa opetella heti ensimmäisiä pieniäkin ohjelmia
tehdessään.
Käytä yhtenäisiä nimiä. Jos kirjoitat muuttujan nimen osat alaviivalla erotettuna, niin hyvä; jos erotat ne isoilla alkukirjaimilla, hyvä niinkin. Mutta älä käytä samassa ohjelmassa nimiä suurinLuku ja pienin_luku. Käytä samoille asioille aina samaa käytäntöä, vaikka funktiot isolla alkukirjaimella ja muuttujat pienellä alkukirjaimella.
Joissakin tapauksissa on olemassa vakiintunut nimeämistapa. Sellaista kannattaa noudattaa. Esimerkiksi Mathematicassa omien funktioiden nimet aloitetaan pienellä alkukirjaimella ja Javassa luokkien nimet aloitetaan aina isolla alkukirjaimella.
Sisennä lähdekoodi ohjelman rakenteen mukaisesti.
Tässä for
-lauseen sisällä olevat lauseet on
sisennetty ja edelleen if
-lauseeseen kuuluva sisempi
lause on sisennetty hiukan enemmän.
for . . .
lause1
if . . .
lause2
end if
lause 3
end for
Sisennystapoja on erilaisia. Tärkeää ei ole minkä tavan valitset, vaan yhtenäisyys. Käytä koko ohjelmassa samaa tapaa esimerkiksi sulkujen paikalle.
Erota aliohjelmat toisistaan parilla tyhjällä rivillä. Erota myös aliohjelman tai funktion sisällä loogiset kokonaisuudet toisistaan. Jos ohjelmassa on alkuvalmistelut, laskentasilmukka ja loppuvalmistelut, erota osat tähän tapaan:
// Alkutarkistukset
assert(n <= 50);
assert(p <= n);
// Tarkistukset OK, lasketaan
. . .
// Lopuksi tulostetaan laskennan tulos
Välilyönneillä voit myös selventää monimutkaista laskua tai ehtoa.
paino<60 & pituus>165
on selkeämpi kuin
paino<60&pituus>165
Muista kommentoida koodisi. Kirjoita jokaisesta aliohjelmasta mitä se tekee, ja tarvittaessa laita itse koodiinkiin kommentteja. Esimerkiksi tähän tapaan:
// Haetaan suurin luku
for (int i=0; i<lukuja; i++)
if (luvut[i] > max)
. . .
// Kuinka moni luvuista on suurempi kuin puolet suurimmasta
for (int i=0; i<lukuja; i++)
if (luvut[i] > max/2)
. . .
Erityisesti mainitse kaikesta, mikä voi yllättää luokan tai funktion käyttäjän. Kerro myös, jos olet ottanut ohjelman osan jostain kirjasta.
(* Laske mahdollisten p-alkioisten osajoukkojen määrä n:stä alkiosta.
Käyttää kaavaa N!/(P! * (N-P)!)
HUOM! Tapahtuu ylivuoto, jos N suurempi kuin 50. *)
function LaskeOsajoukkojenMaara(integer: n, integer: p) : integer
. . .
Muista kuitenkin, että kommentoinnilla ei korvata hyvää nimeämistä.
Ei siis muuttujannimeä oppLuo
ja erillistä kommenttia
muuttujan tarkoituksesta, vaan muuttujalle nimeksi
oppilaitaLuokassa
.
Ihminen ei pysty hahmottamaan tuhatta koodiriviä. Sen sijaan kymmenen ohjelmamoduulia voi hahmottaa, ja jokainen moduuli voi sisältää kymmenen aliohjelmaa, ja aliohjelmat puolestaan kymmenen riviä koodia.
Aliohjelman tai funktion sisälläkin voi jakaa tehtävät alitehtäviin. Käytä väliaikaisia muuttujia ja tallenna välitulokset. Älä kirjoita
tulos=Apply[Times, Map[Sqrt, lista1]-Map[Sqrt, lista2]];
vaan
juuriLista1=Map[Sqrt, lista1];
juuriLista2=Map[Sqrt, lista2];
erotusLista=juuriLista1-juuriLista2;
tulos=Apply[Times, erotusLista];
Tee aliohjelmia, funktioita tai luokkia, jotka huolehtivat yhdestä tehtävästä. Varianssin laskemiseen pitää tietää keskiarvo. Kirjoita erikseen keskiarvon laskeva funktio, vaikket sitä missään yksinään käyttäisikään. Tällöin on paljon helpompi tarkistaa ohjelman toimivuus pala kerrallaan.
Älä tee osien välille turhia riippuvuuksia. Vältä tilannetta, jossa jotakin funktiota voi kutsua vain tietyissä tilanteissa. Varmista, että funktiosi ei muuta mitään sellaista, joka voisi yllättää funktion käyttäjän.
Joskus näkee ratkaisuja, joilla yritetään säästää muutama millisekunti. Toki sekin voi joskus olla tarpeellista, mutta yleensä selkeä koodi on kuitenkin paljon tärkeämpää. Lisäksi joissakin tapauksissa yritys tehostaa ohjelmaa tekeekin siitä hitaamman. Myöskään kaikkia tuntemiaan hienouksia ei välttämättä kannata käyttää. Muutaman koodirivin säästäminen ei kannata, jos sen tuloksena ohjelmaa seuraavalla viikolla lukiessa ei enää ymmärräkään miten se toimii.
Työkalujen käyttö kannattaa opetella kunnolla. Jos kielenä on C++,
älä tee merkkijonoluokkaa vaan käytä valmista string-luokkaa. Matlab
-ohjelmoijan ei kannata kirjoittaa silmukkaa
for i=1:10, a(i)=sin(b(i));
kun saman asian Matlabissa voi sanoa myös suoraan
a=sin(b)
. Delphillä
ohjelmoivan ei kannata käyttää kirjoittaa omaa koodia, jos jokin
Delphin valmis komponentti osaa tarvittavan asian.
Ylläolevista ohjeista tärkeimmät voi tiivistää kolmeen riviin: