Jorin jutut / ohjelmointi

Hyvä ohjelmointitapa

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.

Nimeä järkevästi

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.

Muotoile välilyönneillä ja rivinvaihdoilla

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

Kommentoi

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.

Jaa osiin

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.

Älä kikkaile

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.

Tunne käyttämäsi kieli

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.

Tiivistelmä

Ylläolevista ohjeista tärkeimmät voi tiivistää kolmeen riviin: