Ohjelmointikäytännöt

**Ohjelmointikäytännöt** ovat joukko ohjeita, joilla voidaan määrittää ohjelmistotuotantoprosessissa käytetyt menetelmät ja tuotetun lähdekoodin ulkoasu sekä rakenne. Pyrkimyksenä on tuottaa luettavampaa, virheettömämpää ja helpommin ylläpidettävää ohjelmakoodia. Ohjelmointikäytännöillä ei ole vaikutusta käännettyyn binääriin, vaan ne ovat olemassa ihmistä varten. Ohjelmointikäytännöiksi voidaan lukea esimerkiksi säännöt tiedostorakenteesta, ohjelmointiympäristöstä, nimeämisestä, sisentämisestä, kommentoinnista jne.

## Etuja
### Ylläpidettävyys
Tutkimusten mukaan tyypillisen ohjelmistoprojektin elinkaaresta 80&nbsp;% kuluu ohjelmiston ylläpitoon. Tästä ajasta 50–60&nbsp;% menee koodin lukemiseen ja ymmärtämiseen. Ohjelmointikäytäntöjen avulla voidaan selkeyttää koodin rakennetta ja parantaa luettavuutta. Näin ollen ohjelmiston ylläpito helpottuu ja tulee ylipäätään mielekkääksi ja mahdolliseksi.

### Laatu
Tilastollisesti ohjelmistoissa esiintyy tietyntyyppisiä virheitä useammin kuin muita virheitä. Myös yksilöllisesti tietyillä ohjelmoijilla on tapana toistaa tietyn tyyppisiä virheitä. Ohjelmointikäytännöillä voidaan suojautua tällaisia virheitä vastaan. Säännöillä voidaan esimerkiksi rajoittaa globaalien muuttujien käyttöä tai vaatia osoittimien nollaamista käytön jälkeen.

Koodin katselmointi on tehokas tapa parantaa ohjelmiston laatua. Jos kaikki projektin jäsenet toimivat samojen käytäntöjen mukaisesti, on katselmoijien helpompi lukea koodia, helpompi tehdä oletuksia koodista ja helpompi löytää virheitä.

### Ennustettavuus
Vakiintunut käytäntö ohjelmistorakenteen ja tiettyjen menetelmien, kuten virheenkäsittelyn suhteen auttaa ohjelmoijia tekemään enemmän oletuksia koodista. Jo pelkästään tiedostorakennetta katsomalla he voivat nähdä mistä löytyy heidän etsimänsä koodinpätkä ja itse koodinpätkää lukemalla he voivat olettaa miten se toimii alemmalla tasolla. Jos esimerkiksi virheiden käsittelyyn, syötteiden lukemiseen ja luokkien rajapintoihin on yhteinen käytäntö, se luo koodille loogisen rakenteen, jota muiden ohjelmoijien on helppo seurata. Ilman vakiintunutta käytäntöä se on tehtävä lukemalla ohjelmaa järjestelmällisesti läpi.

### Automatisointi
Ohjelmointikäytännöt eivät tee ohjelmoinnista hitaampaa. Se tekee siitä nopeampaa. Ohjelmoinnissa useimmat asiat voi tehdä monella vapaavalintaisella tavalla. Jos näihin vapaavalintaisiin tapoihin on vakiintunut käytäntö, niin samaa valintaa ei tarvitse tehdä joka kerta uudestaan. Lisäksi muut samaa käytäntöä noudattavat ohjelmoijat tietävät heti mistä on kysymys.

Joidenkin käytäntöjen avulla monet tehtävät voidaan automatisoida kokonaan. Esimerkiksi ohjelmiston dokumentointi voidaan automatisoida käyttämällä Javadocin tai Doxygenin tunnistamaa ohjelmointityyliä.

### Ohjelmointikielten puutteet
Ohjelmointikäytännöillä voidaan kompensoida ohjelmointikielessä esiintyviä puutteita ja suojautua mahdollisesti vaarallisia kohtia vastaan. Esimerkiksi nimeämiskäytännöillä voidaan korvata Pythonista puuttuvat vakiot. Yksinkertaisella nimeämissäännöllä voidaan koodin lukijalle kertoa onko muuttujaa tarkoitus kirjoittaa, lukea vai sekä että.

## Kritiikkiä
Ohjelmointikäytäntöjä on yleisellä tasolla kritisoitu varsin vähän. Tyypillisesti kritiikki kohdistuu yksittäisiin käytäntöihin, jotka voivat olla huonosti määriteltyjä tai projektiin sopimattomia. Yleisellä tasolla ohjelmointikäytäntöjen on kritisoitu hidastavan ohjelmointia lähinnä kahdesta syystä.

Ensimmäinen syy koskee hyvin pieniä projekteja, joissa ohjelmointikäytäntöjen opettelu tuo ylimääräisen vaiheen projektin alkuun, eikä käytäntöjen tuoma hyöty pääse koskaan esille. Sasa M. Deklevan tutkimuksen mukaan hyvien ohjelmointikäytäntöjen mukaan kirjoitettuun koodiin todella käytetään enemmän aikaa kuin ilman sääntöjä kirjoitettuun koodiin. Syy tosin on siinä, että ilman sääntöjä kirjoitettu koodi kirjoitetaan tyypillisesti kerran ja heitetään sen jälkeen romukoppaan. Sääntöjen mukaan kirjoitettu koodi puolestaan käytetään uudestaan ja mahdollisesti laajennetaan tai muokataan useampiin tarkoituksiin soveltuvaksi. Tämä pätee myös ohjelmoijan omaan käyttöön kirjoittamalleen koodille. Toinen kritiikkiä vastaan puhuva asia on, että luettavan koodin kirjoittaminen kehittää ohjelmoijalle rutiinin kirjoittaa luettavaa koodia projektin koosta riippumatta.

Toinen kritiikin syy koskee puolestaan tyypillisesti suurempia projekteja. Projektin koon ollessa hyvin suuri se näkyy usein lisääntyneinä sääntöinä, joita projektin jäsenet joutuvat opettelemaan. Vaarana on että säännöistä tulee ristiriitaisia ja että niitä tulee liikaa opeteltavaksi. Huoli on aiheellinen jos ohjelmointikäytäntöjen määrä ja laatu ei pysy hallinnassa. Vaikka ohjelmointikäytännöt ovatkin hyvä asia, on niissäkin liiallisuuksiin meneminen pahasta.

## Esimerkkejä

### Nimeämiskäytännöt
Java-kielen nimeämiskäytäntöjä ovat ehdottaneet ja vakiinnuttaneet useat Java-yhteisöt kuten Sun Microsystems, Netscape, AmbySoft jne.

Esimerkki Sun Microsystemsin nimeämiskäytännöistä:

Symbian-alustalla oli useita eri luokkien nimeämisiä niiden käyttötapojen mukaan. Luokan etuliitteenä oli T, S, C, R, M tai N -kirjain.

Linux-ytimen ohjelmointioppaassa suositellaan Kerninghan&Ritchie (K&R C)-tyyliä: tyyli poikkeaa GNU-projektin käytännöistä sekä Unkarilaisesta notaatiosta.

### Kontrollirakenteet
Loogisten kontrollirakenteiden oikeanlainen käyttö helpottaa koodin tulkitsemista. Esimerkki pseudo-koodina:


```
i = 0
 while i < 5
   print i * 2
   i = i + 1
 end while
 print "Ended loop"
```


Yllä oleva koodinpätkä noudattaa nimeämis- ja sisennyskäytäntöjä, mutta seuraavassa esimerkissä käytetty for-rakenteen käyttö tekee koodista helpommin luettavan:


```
for i = 0, i < 5, i=i+1
   print i * 2
 print "Ended loop"
```


Aaltosulkeita hyödyntävissä ohjelmointikielissä yleinen tyyli on käyttää sulkeita kontrollirakenteiden yhteydessä silloinkin, kun niiden käyttö on syntaksin kannalta samantekevää.


```
for (i = 0 to 5) {
   print i * 2;
 }
 print "Ended loop";
```


Tällä pyritään estämään bugeja, joiden jäljittäminen voi olla aikaavievää, kuten puolipisteeseen päättyvä kontrollirakenteen käyttö, joka on tyypillinen virhe:


```
for (i = 0; i < 5; ++i);
    printf("%d\n", i*2);    /* Sisennys antaa helposti väärän kuvan siitä, että rivi kuuluu silmukan sisään. */
 
 printf("Ended loop");
```


...tai tilanteita jolloin silmukkaan lisätään jälkeenpäin uusi rivi:

```
for (i = 0; i < 5; ++i)
    fprintf(logfile, "loop reached %d\n", i);
    printf("%d\n", i*2);    /* Sisennys antaa helposti väärän kuvan siitä, että rivi kuuluu silmukan sisään. */
 
 printf("Ended loop");
```


## Lähteet

## Aiheesta muualla
### Ohjelmointikielikohtaisia käytäntöjä

*Ada: Ada 95 Quality and Style Guide: Guidelines for Professional Programmers 
*C: Micrium C Coding Standard  
*C++: Quantum Leaps C/C++ Coding Standard 
*Erlang: Erlang Programming Rules and Conventions  
*Java: Code Conventions for the Java Programming Language 
*Lisp: Riastradh's Lisp Style Rules 
*Perl: Perl Style Guide 
*PHP::PEAR: PHP::PEAR Coding Standards 
*Python: Style Guide for Python Code 
*Ruby: Good API Design