Ohjelmoinnin peruskirja

Antero Saarenpää, Kalle Takkinen Teknolit 1998, ISBN 952-5159-55-8

Arvostelut: Vesa Lappalainen, vesal@mit.jyu.fi. Mielipiteet ovat täysin omiani ja joku toinen saa olla niistä vapaasti erimieltä.

Ensiksikin: Kaikkea sitä saa painovapauden nimissä julkistaa. Ja vielä kovissa kansissa! Kirjan takakanneessa kehutaan että tekijöillä on yli 10 vuoden kokemus eri ohjelmointiympäristöistä. Olisi kiva, kun tekijät olisivat joskus käyttäneetkin noita ympäristöjään.

Kenelle kirja on suunnattu? Nähtävästi sellaiselle, joka ei ole koskaan kuullut ohjelmoinnista. Jos sellainen lukija jostakin syystä joskus pääsee sivulle 78 saakka (sivuja yhteensä 169), täytyy hänen olla todella kiinostunut asiasta. Ja jos hänestä tästäkin kirjasta huolimatta tulee ohjelmoija, täytyy hänen olla lisäksi vielä todella hyvä. Niin hyvä, että hän olisi samantien voinut aloittaa jollakin kunnollisellakin kirjalla.

Miksi sanon noin rankasti?

"Puoliohjelmointi"

Jos kirjan alkuosa uhrataan sinänsä tärkeälle vuokaavio- ja algoritmitekniikalle (kuka on kuullut aikaisemmin sanan puoliohjelmointi?), niin voisi sen yrittää tehdä niinkin, että asialle annetaan jotakin sisältöä. Nyt "puoliohjelmointia" räpelletään ilman suunnitelua. Ensin mätkitään kassan joitakin lauseita ja sitten niitä pyöritellään edestakaisin ja todetaan esimerkin olevan nyt kunnossa. Kirjan alussa varoitellaan miten käy jos talohankkeeseen ryhtyy ilman suunnittelua. Tällä perustellaan puolikirjaa "puoliohjelmointia". Kuitenkin kirjan "puoliohjelmointi" on niin lähellä jotakin ohjelmointikieltä, että samantien olisi voinut käyttää kieltä.

Jos esitetään algoritmista ohjelmointia, niin voisi yrittää ensin saada lukijalta kaivettu esiin jo olemassa olevaa tietoa ja muuttaa tätä algoritmiseksi. Ja tällöin minusta on paljon tärkeämpää ensin saada lausuttua ongelman looginen ratkaisu kuin kirjoittaa se heti "puoliohjelmaksi". Nyt kirjassa käydään samat asiat (ehdot, toistot, muuttujat) läpi kolmeen kertaan: vuokaavioissa, "puoliohjelmoinnissa" ja varsinaisessa C-ohjelmoinnissa. Tuntuisi että aloittelijan kannalta vaikka rinnakaisempi käsittelytapa olisi ollut parempi.

Otetaanpa kirjasta esimerkki: "Seuraavaksi tutustutaan esimerkkien avulla siihen, miten pienessäkin ohjelmassa voi olla monta kohtaa, jotka laiminlyötyinä aiheuttavat ongelmia".

Alku
  Summa = 0
  Pakkaspv = 0
  Pakkasasteet = 0
  Toista
    Jos (Pakkasasteet <= 0) niin
      Summa = Summa + Pakkasasteet
      Pakkaspv = Pakkaspv +1
    Loppu-jos
    Kysy Pakkasasteet
  Loppu-kun (Pakkasasteet > 0)
  Tulosta "Peräkkäisiä pakkaspäiviä oli" Pakkaspv
  Tulosta "Keskimäärin pakkasta oli " Summa/Pakkaspv
Loppu

Tähän on päädytty pitkän vatvomisen jälkeen selvästi erittelemättä mitä lopulta halutaan Aluksi oli selkeä lähtökohta, mutta (sinänsä oikeaoppisesti minusta näyttämällä välillä miten ajatus voi mennä harhaan) sitten on pyöritetty "puoliohjelmaa" edestakaisin lisäten ehto sinne tänne jo lopulta on päädytty tuohon. Vielä seuraa yksi "ahaa": nollalla jako. Jos edes pienen pöytätestin tuolle ohjelmalle tekisi, niin ei tuosta tarvitsisi olla huolissaan vaan jostakin muusta (harjoitustehtävä). Erikseen on oikein huomautettu, että ensimmäisen kierroksen 0:n lisääminen ei aiheuta ongelmia. Välillä varsinainen vika huomattiin ja käytettettiin ehtoa Pakkasasteet < 0 mutta sitten huomattiin, että 0 on pakkaspäivä ja sekin pitää lisätä.

Mistä ihmeestä on kotoisen se koulukunta, joka niin voimakkaasti suojelee "goto"-lausetta, että tuossakaanei esimerkiski uskalleta aloittaa kysymyksellä ja jos se on syötön lopettava, niin ei reilusta katkaista silmukkaa. Minusta on todella epäpedagogista käyttää do-while -rakennetta tilanteessa, jossa se ei ole omimmillaan. Esimerkiksi edellisessä on tietysti ajateltu (ja ensimmäisissä esimerkeissä olikin) että silmukkaan valutaan aina lukemaan vähintään yksi arvo. Sitten kuitenkin suurin osa silmukasta on lopulta suljettu ehtolauseen sisään.

Oma ratkaisuni "puoliohjelmalla olisi": Luetaan pakkaspäiviä kunnes ne loppuvat. Kunkin pakkaspäivän kohdalla lisätään päivien lukumäärää ja pakkassummaa" :

Alku
  Summa = 0
  Pakkaspv = 0
  Toista
    Kysy Pakkasasteet
    Jos (Pakkasasteet > 0) niin lopeta kysely
    Summa = Summa + Pakkasasteet
    Pakkaspv = Pakkaspv +1
  Jatka toista 
  ... plääp plääp 0 tilanteesen jne...
Loppu

Ero on tietysti pieni, mutta minusta merkittävä. Silmukka ei sisällä turhia testejä ja erityisesti silmukan lopetusehto ei esiiny koodissa 2x (kerran lopetusehtona ja toisen kerran ehdon komplementtina suojattaessa liialta suorittamiselta).

Taulukot

Taulukot ovat ilman muuta tärkeä osa ohjelmointia. Mutta miksi niitä selitettäessä ei ole yhtään kuvaa taulukoista? Ja sitten annetaan esimerkki kaksiulotteisesta taulukosta, jonka ensimmäinen sarake on kokonaisluku, toinen merkkijono ja kolmas reaaliluku. Ja tähän liittyvä esimerkki on kuin 70-luvun Pascal-kurssilta, jossa käyetään hirveästi lippuja ylläpitämään silmukkaa tilnateessa, jossa selkeä silmukan katkaisu olisi vähentänyt koodista useita rivejä ja tehnyt siitä huomattavasti selkeämmän. Jos joku tuosta esimerkistä oppi kaksiulotteisen taulukon, niin hyvä on!

Aliohjelmat

Niistä ei puhuta sanaakaan koko kirjan alkuosassa. Itse pidänm aliohjelmaa jopa silmukkaa tärkeämpänä rakenteena. Erityisesti aloittelijan kannalta. On erittäin vaikea saada sellaista ihmistä tekemään aliohjelmia, jotka on opetettu kirjoittamana koko roska samaan kasaan. Helpompi on opettaa olemaan tekemättä, jos joskus näkisi sellaisen, joka tekee aliohjelman "turhasta" (en ole koskaan nähnyt).

Ylläpito

Epäilemättä ohjelmoinnin tärkeimpiä osa-alueita. Tekijä kertee elävänä esimekrkinä 2000 rivin ohjelmasta. Meillä harjoitustyötkin ovat tätä isompia. Ehkä tästä kuultaa tekijöiden kokemus todelliseen ohjelmointiin.

C-kieli

Vaikka seuraavassa on viitattu sivuihin, ja joka sivulle ei ole viitattu, ei tämä tarkoita että asia olisi moitteetonta noilla muillakaan sivuilla.

Sivulla 76 nähdään jo vilaus ensimmäisestä ohjelmasta (void main(void)!). #include on selitetty hieman väärin, mutta sallittakoon "pieni valkoinen valhe" kun aloittelijasta on kysymys. Makuasia on tietysti ohjelman sisennys, mutta kyllä minä sisentäisin pääohjelmankin.

s. 81: // Ollaan opettavinamme C-kieltä, mutta komentit on //-merkeillä! No toimiihan ne kirjan mukana tulevassa kääntäjässä (Borland C++ 4.5 :-(

s. 89: Itse käyttäisin mielluummin double-tyyppiä aloittelijalle. Ne harvat tapaukset, joissa float on parempi, osaa jo ratkaista sellainen ohjelmoija, joka siihen törmää.

s. 90: Lainaus kirjasta: char etunimi[10] = "Iivari"; "Huomaa että merkkijonotaulukolle on varattu usemapi alkio kuin mitä merkkijonossa on kirjaimia. Tämä siksi, että järjestelmä lisää joissakinn tapauksissa merkkijonon loppuun merkinnän \0." Olisi kiva tietää milloin ei. Miksi 10 kun 7 riittäisi?

s 95: Lainaus kirjasta: &-merkintää muuttujan nimen edessä käytetään silloin, kun halutaan lukea yksi perustietotyyppiä olevan muuttujan arvo. Olisi samalla voinut kertoa edes osan totuutta! Ilkeämielinen lukija jopa saattaa jäädä siihen uskoon, että taulukoitakin voisi lukea scanf-funktiolla. Ja olisi samalla rehellistä sanoa, etti scanf:llä käytännössä voi lukea merkkijonoja (jos tekijä lienee itse tätä edes huomannut).

s. 107: Miksi on kauniisti kirjoitettu hinta > 10 && hinta < 100 (tosin tämänkin olisi voinut opettaa 10 < hinta && hinta < 100 ja samalla kertoa miksi 10 < hinta < 100 ei toimi), kun kohta rumasti kirjoitetaan 5>4&&10<20. Ja vaikka sulut eivät olekkaan pakollisia, niin niitä voisi silti suositella käytettäväksi.

s. 118: Omituinen tapa sisentää do-while -lause ("syntaksi-esimerkissä"). Olisiko kannattanut näyttää mitä ohjelmat tulostavat? Ja olisiko kannattanut paremmin vertailla milloin mitäkin silmukkaa kannattaa käyttää. Nyt kaikki esimerkit ovat ilmeisiä for-silmukoita (tiedetään kierrosmäärä jo silmukkaan tultaessa).

s. 123: Miksi ihmeessä pitää opettaa kirjoittamaan funktion prototyyppi ensin ja aliohjelmat loppuun. Jo yksin tästä seuraa sellainen henkinen vastustus aliohjelman kirjoittamiseen, että mieluummin liimaa-leikkaa kodia, kuin kirjoittaa aliohjelman. Lisäski ilman ennalta olevia prototyyppejä tehdystä ohjelmasta karsiutuu automattisesti pois piilorekursiot. Hyvänä esimerkkinä piilorekursiosta on usein kursseillani oppilaidne tekemä virhe: menusta kutsutaan alimenua. Alimenusta poistutaan kutsumalla päämenua. Tämä on mahdotonta kääntää, jos ei käytetä funktioidan etukäteisesittelyä! Tämä on aloitteleijna kirja ja silloin sen opettamien tapojen pitäisi olla sellaisia, jotka ovat turvallisia aloittelijoiden käsissä.

Yhtään hyödyllistä aliohjelmaa ei kirjassa ole onnistuttu esittämään. Miksi kirjoittaisin aliohejlmia, kun koodi olisi ollut lyhempi ilman niitä. Lisäksi yksikään aliohjelmista (no ehkä keskiarvon laskeminen kahdelle luvulle :-) ei ole perusteltu edes uudelleenkäytettävyyden takia. Mitään aliohjelmaa ei edes kutsuta kahta kertaa. Aliohjelmien parametrinvälitysmekanismi on täysin kertomatta.

Tiedostonkäsittelystä "opetetaan" vain merkki kerrallaan lukeminen ja kirjoittaminen. Aloittelijako tästä hyötyy?

s. 144: Lue kolme lukua ja tulosta ne järjestyksessä. Miksi tällaisia vastauksia mennään esittämää?

s. 147: Muuttujia esitellään kesken koodin ihankuin kyseessä olisi jokin C++ -ohjelma! Jos ruvetaan tekemään C++ -ohjelmaa, olisi samantien voitu ottaa käyttöön tietovirrat ja merkkijonot ja referenssimuuttujat ja saatu aloittelijallekin turvallinen kieli! Ja mihin vierellä olevaa "puoliohjelmointia" tarvitaan, jos se rivi riviltä samaan kuin vastaava "C-ohjelma"!

s. 164-169: Kirjassa on käytössä omituinen tyyli sisentää, mutta tässä esimerkissä ei enää kukaan pysy mukana.

Hakemistokin kirjaan on tehty. Lienee teijät kuulleet että jokin sellainen pitäisi olla. esim. Peräkkäisrakenne löytyy Puoliohjlemoinnin jälkeen. Ehkä aakkostaminen on suoritettu jollakin kirjan ohjelmalla? While-silmukkaa, for-silmukkaa jne. ei ole. Aliohjelma-hakusana viittaa kohtaan jossa sanotaan: "Yhteenlaskuja suorittava aliohjelma voisi palauttaa esimerkiksi kokonaislukuja ja niin edelleen". Tuskin tarvitsee enää jatkaa?

Lopuksi

On siinä ja siinä, että tämä "teos" kelpaisi jonnekin takahikiän peruskoulun valinnaiskurssille monisteena, saati sitten kovakantiseksi kirjaksi.

Positiivisena seikkana kirjasta voisi todeta ettei siitä löytynyt pikaisella lukemisella yhdys sana virheitä :-)