Sivut

lauantai 13. helmikuuta 2016

Toimivan ohjelmointimateriaalin luominen ei olekaan niin yksinkertaista...

Ohjelmointia osaavan ihmisen on lähes mahdotonta laskeutua aloittelijan tasolle. Tämä tuli selväksi monesta palautteesta, joita sain Koodiaapinen MOOC - betan myötä. Toisaalta ohjelmointimateriaalia ei pysty tekemään ellei osaa ohjelmoida sujuvasti. Tämä on mielenkiintoinen rakenteellinen ongelma, jonka jokainen ohjelmointimateriaaleja kehittelevä henkilö joutuu kohtaamaan. Tässä projektissa tähän ongelmaan on pureuduttu kahdellakin tavalla: materiaalia testataan oikeilla oppilailla ja opettajilla (myös alottelijoilla) ja materiaalia käytetään Koodiaapinen MOOC:ssa opettajien kouluttamiseen (myös aloittelijoiden). Racket-iskuryhmän sekä MOOC-viikkopalautteen voimin,  virheistä oppimalla ja työtä tekemällä, materiaali saadaan pikkuhiljaa vietyä lähemmäs aloittelijan tasoa.

Koska tiesin jo ennen materiaalin tekemistä, että se ei tule olemaan heti aivan täydellistä,  projektisuunnitelmassa tämä kevät on varattu materiaalin "viimeistelyyn". Tämän blogikirjoituksen on tarkoitus kirkastaa ajatusta siitä miten ja mihin suuntaan sitä pitää muovata.

Rakenne

Koodausta kouluun materiaalin rakenne, jako oppilaan tehtäviin, koodarin käsikirjaan sekä opettajan oppaaseen on toimiva. On hyvä, että on olemassa Koodarin käsikirja, josta löytää helposti tarvitsemansa tiedon, ja joka muuttuu hitaasti. Koska samaa tietoa tarvitaan monessa tehtävässä, teorian on järkevämpää linkittää tehtäviin oikea sivu Koodarin käsikirjasta kuin kirjoittaa samaa asiaa moneenkertaan. Oppilaan tehtävät osion tarkoitus oli alunperin esitellä tehtäväideoita ja pohjia niin, että opettajat voisivat niiden avulla kehittää itse lisää harjoituksia. Sen on toimittava aluksi myös "täydellisenä" materiaalipankkina niille opettajille, jotka aloittelevat ja joilla ei ole aikaa tai taitoa luoda omia tehtäviä. Tämän materiaalipankin tarkoitus ei ole jatkossakaan sisältää "kaikkia mahdollisia tehtäviä", koska niitä on rajattomasti. Opettajan opas sisältää opettajaa kiinnostavaa taustatietoa mm. tavoitteista, linkit materiaaliin liittyviin opetusvideoihin sekä erimerkkiratkaisut kaikkiin tehtäviin. Eliademy on sinänsä toimiva järjestelmä materiaalin tallentamiseen vaikkakin se on usein melko hidas. Tämä rakenne tullaan siis säilyttämään jatkossakin.



Etenemisjärjestys ja tehtävien vaikeustaso

Lausekielinen ohjelmointi on vaativaa sen takia, että yksinkertaistenkin ongelmien ratkaisu vaatii tietyn minimityökalupakin. Oppija ei kuitenkaan pysty ottamaan vastaan määräänsä enempää tietoa kerralla, joten asioita pitäisi opetella yksi kerrallaan. Syksyn materiaali oli jaoteltu näin:

Alkeet: Peruslaskut
  • DrRacket/WeSchemen käyttö, Racketin syntaksi
  • peruslaskulausekkeet lukuarvoilla, evaluointi, laskujärjestys (lausekkeiden yhdistäminen)
Alkeet: Kuvat
  • peruskuvat, kuvien yhdistäminen (lausekkeiden yhdistäminen), debuggaaminen
  • kirjaston käyttäminen (2htdp/image)
  • määrittelyt (define)
Alkeet : BONUS
  • Racket turtle - perusteet
Perusteet: Funktiot
  • funktion määritteleminen
  • ongelman jakaminen useampaan funktioon
  • funktion suunnitteluportaat menetelmä ml. check-expect ja stub
Perusteet: Totuusarvot ja ehtolause
  • totuusarvot, vertailuoperaattorit, predikaatit, ehtolause, valintalause, Boolean operaattorit
Perusteet: Sovellukset
  • käyttäjän syötteen tutkiminen (display-read)
  • animate ja big-bang (2htdp/universe)
Jatko: Silmukat
  • silmukat higer order funktioiden avulla (map, foldl)
  • random
  • Racket Turtle - jatko
Järjestys oli sinänsä looginen funktiot-logiikka-silmukat mutta ongelmaksi tuli se, että yhdessä aiheessa mentiin jo hyvin vaikeisiinkin tehtäviin, "oppitunnilla" tuli aivan liikaa asiaa ja oli myös vaikea keksiä mielekkäitä tehtäviä, joissa tarvitaan vain ja ainoastaa funktioita (ei logiikkaa). Materiaali pitäisi siis rakentaa niin, että eri osa-alueita: funktiot ja muuttujat (abstraktio), konditionaalinen logiikka (algorimit, ehtolause, Boolean logiikka), toistorakenteet (algoritmit, rekursio, higher order funktiot) sekä hyvät ohjelmointikäytänteet (testaus, suunnittelu, ongelman jakaminen osiin) tulisivat rintarinnan ja etenisivät alkeellisemmista rakenteita ja käytänteistä vaativampiin. Eli ensin opitaan ratkaisemaan ongelmia hieman alkeellisemmilla työkaluilla, myöhemmin ehkä nähdään jotain hieman monimutkaisempaa mutta tehokkaampaa.
Sen lisäksi, että asiat tuodaan oppilaalle pienissä paloissa, tämän tutkimuksen mukaan ne kannattaisi tuoda käyttöön kolmiportaisen kaavan kautta asteittain (use-modify-create):
  1. käyttäminen (käytetään valmista funktiota esim. 2htdp/image kirjastoa)
  2. muokkaaminen (muokataan valmiin funktion koodi tekemään jotain muuta)
  3. luominen (tehdään täysin oma funktio)
Tehtävien etenemisjärjestykseen vaikuttaa omalta osaltaan juuri valmistumaisillaan oleva Tampereen seudullinen OPS. OPS luonnoksessa 7. luokalla harjoitellaan peruslaskulausekkeita tai kuvien piirtämistä sekä ehtolauseen käyttöä. Koodausta kouluun materiaalin "alkeet" osio soveltuukin jo sellaisenaan hyvin 7. luokan OPS sisältöihin mutta siitä puuttuvat vielä yksinkertaiset tehtävät, joilla tutustutaan totuusarvoihin sekä ehtolauseisiin. 8. luokalla OPS vaatii ratkomaan ongelmia algoritmien avulla (esim. pelien tai animaatioiden muodossa), mikä vastaa Koodauta kouluun "perusteet" osiota, kunhan siihen lisätään harjoituksia rekursiivisista funktioista. 9. luokalle OPS sijoittaa funktioiden ja muuttujien käytön sekä ongelman ratkaisemiseen osissa. Tähän yhteyteen sopisivat Koodausta kouluun materiaalin tehtävät, joissa kirjoitetaan itse omia funktioita/apufunktioita ja käydään läpi funktion suunnitteluportaat menetelmä.

Kun lähdin ohjelmointia opettamaan, pedagoginen ajatteluni tukeutui siihen, että "kopioimalla" (esim. kirjasta tai tutoriaalista koodirivejä) ei voi oppia ohjelmointia. Käytäntö on kuitenkin näyttänyt, että ensimmäinen vaihe lausekielisen ohjelmoinnin oppimisessa on se, että ensin kopioidaan jotain, vaikkapa seurataan MOOC:in vetäjän tutoriaalivideota ja koodataan samalla tai seurataan opettajan esimerkkiä luokassa ja koodataan samalla. Tässä ei vielä tapahdu varsinaista asian syväoppimista, vain se on tapa tutustua uuteen rakenteeseen tai menetelmään. Tämän jälkeen asiaa harjoitellaan tarkasti rajattujen tehtävien avulla, sellaisten joissa ongelma on valmiiksi muotoiltu ja ratkaiseminen on melko suoraa koodin kirjoittamista, tarvittavat tiedot on annettu ja  käytetään niitä rakenteita tai menetelmiä, joita on juuri tutustuttu. Viimeinen taso, jossa varsinainen asia ymmärretään on avoin tehtävä, jossa keksitään itse ongelma ja muotoillaan sille ratkaisu tai jatketaan koodia tekemään sellaista mitä ei ole valmiiksi määritelty.     

Melkoinen määrä siis asiaa... Tämä ei tarkoita, että kaikkien oppilaiden ja kaikkien ryhmien olisi käytävä aina kaikki tämä. Tämä on vain polku, jonka avulla materiaali rakennetaan etenemään loogisesti sille tasolle asti, johon tämän materiaalin puitteissa on järkevää edetä. Oppilaiden kanssa tehdään se, mihin kyseinen ryhmä kykenee. Materiaalin on joustettava joka suuntaan.


Opiskeltavien asiakokonaisuuksien portaittainen jako 

Funktiot ja muuttujat:
  1. valmiiden funktioiden käyttäminen a) Racket BSL, b) kirjasto
  2. globaalin muuttujan määrittely (define)
  3. funktion käsite, funktion määritteleminen, valmiin funktiorungon täydentäminen tekemään haluttu asia (stub valmiina)
  4. funktion testaaminen interaktioikkunasta
  5. funktion parametrien nimien keksiminen (stub vain osittain valmiina)
  6. funktion toiminnallisuuden jakaminen kahteen eri funktioon (funktio kutsuu toista, valmista funktiota)
  7. funktion testaamisen automatisointi check-expectin avulla
  8. funktion toiminnan suunnittelu ennen koodaamista check-expect:ien avulla
  9. kokonaan oman funktion suunnittelu analysoimalla muuttujat ja vakiot, stub:in kirjoittaminen, check-expectien kirjoittaminen
  10. uuden toiminnallisuuden jakaminen omiin osafunktioihin
  11. funktion sisäiset muuttujat (let)
  12. inline funktiot (lambda)
  13. call-back funktiot
Konditionaalinen logiikka:
  1. tutustuminen totuusarvoihin true/false
  2. vertailuoperaattorit (<, >, <=, >=, =)
  3. predikaatit eli funktiot jotka palauttavat totuusarvoja (number?, positive?)
  4. ehtolause (if)
  5. sisäkkäiset ehtolauseet
  6. Boolean operaattorit (and, or, not)
  7. valintalause (cond) 
Toistorakenteet:
  1. käytetään kirjaston toteuttamaa toistorakennetta (Racket Turtle repeat)
  2. tehdään funktio, joka kutsuu itse itseään ilman lopetusehtoa (funktiolla sivuvaikutuksia)
  3. lisätään silmukalle lopetusehto parametrin avulla
  4. parametrin käyttäminen silmukan tilan tallentamiseen 
  5. listan iterointi rekursiivisesti
  6. listan iterointi higer order funktioiden avulla
Tietorakenteet:
  1. tietotyypit a) luku, merkkijono, b) kuva, c) totuusarvo
  2. listan käyttäminen staattisena parametrina (Racket turtle, display-read)
  3. listan käyttäminen dynaamisesti tallentamiseen (lisääminen, poistaminen, member?)
  4. tietueen käyttö
Hyvät ohjelmointikäytänteet:
  1. muuttujien ja funktioiden nimeäminen kuvaavasti
  2. vakioarvojen määrittely muuttujan avulla (single control point, turhan toiston välttäminen)
  3. funktio tekee vain yhden asian (modulaarisuus, ei toisteta turhaan)
  4. funktion testien jättäminen koodiin (check-expect)
  5. käytetään funktioita aina kuin mahdollista (uudelleen käytettävyys, testattavuus)
  6. koodin testattavuus (keskitetään sivuvaikutukset yhteen paikkaan, muu toiminta funktioihin)
Automatisointiajattelu:
  1. ongelman jakaminen osiin ja ratkaiseminen pala kerrallaan
  2. toistuvien rakenteiden huomaaminen (patterns)
  3. yksittäinen ratkaisun yleistetäminen (abstraktio)
  4. vaiheettaisten ohjeiden laatiminen ongelman ratkaisemiseksi (algoritmi) 
Nämä jaetaan kevään ainaka oppitunteihin (6 kpl) sekä BONUS tunteihin (3 kpl). BONUS tunnit sisältävät oppilaiden kannalta ehkä mukavimmat sovellukset (Turtle, animaatio, pelit). Viimeinen extra-osio tulee sisältämään materiaalia lähinnä kerhoille ja valinnaisaineena kurssia suorittaville.

Uusi tuntijako  

Tehtäväsetit pyritään rakentamaan niin, että 3 ensimmäistä tehtävää ovat helpohkoja suoraviivaisia tehtäviä, joiden tekeminen riittää asian perustasoiseen hallintaan. Tehtävissä voi olla mukana myös ns. lisähaaste nopeimmille (saman tiedoston lopussa). Tämän lisäksi on tarjoalla 3 haastavampaa tehtävää, nopeammille oppilaille tai sellaisille ryhmille, joiden lähtötaso on korkeampi tai joilla on enemmän aikaa käytettävänä ohjelmointiin (esim. painotusluokat tai valinnaisaineet).

Tässä vielä hahmotelma eri osa-alueiden jakautumisesta eri vuosiluokille:


Videot

Opettajan materiaalia sekä Koodiaapinen MOOC:ia varten tekemäni ohjelmointivideot ovat olleet käytössä myös oppitunneilla vaikka niitä ei ole tehty, eikä suunniteltu oppilaiden käyttöön. Videoita saa toki käyttää tunneilla, jos ei koe niitä liian pitkä piimäisiksi. Tavoitteenani olisi tehdä lyhyempiä  oppitunnille sopivampia opetusvideoita keskeisimmistä teorian kohdista, tosin tällä hetkellä tämä näyttäisi jäävän seuraavaan syksyyn... Näiden videoiden tarkoitus olisi selventää järjestelmän toimintaa ilman koodia, eli kirkastaa sitä mitä konepellin alla pyörii eli auttaa opiskelijaa muodostamaan selkeämpi "notional machine" kaiken tauhkan alta. Lisää tämän "käsitteellisen koneen" merkityksestä automatisointiajattelun synnyssä löytyy täältä.

Näiden suuntaviivojen myötä alkaa tehtävien uudelleen muotoilu sekä järjestäminen. Myös kevään MOOC seuraa tätä uutta jakoa. Katsotaan millaista palautetta nyt saadaan. 

Ei kommentteja:

Lähetä kommentti