Avoin yliopisto Java-ohjelmointi koe 25.6.2003 tehtävä 1 Arvosteluperusteet Antti Vähäkangas Tehtävä 1 oli hyvin samankaltainen kurssikokeen 18.12.2002 tehtävän 2 kanssa. Yhdenmukaisen arvostelun takaamiseksi eri kurssien välillä olen käyttänyt Hannu Räisäsen arvosteluperusteita sopivasti muokattuna (Hannu tarkasti syksyn 2002 2. koetehtävän). --- Tehtävä arvosteltiin vähentävällä systeemillä, siis erilaiset virheet pisteytettiin ja vähennettiin maksimipistemäärästä (18 pistettä). Mikäli saavutetut pisteet laskivat tällä systeemillä alle kuuteen pisteeseen, alettiin vastauksesta etsiä ansioita, joiden perusteella opiskelija saavutti 0-5 pistettä. Vähennykset tehtävään 1a: ----------------------- a) privaatti koodikenttä ei final : -0p Tätä vähennystä ei tehty, vaan katsottiin, että koska luokassa ei ole aksessoreja arvon muuttamiseen, suojaus on riittävä. b) laskuri ei static : -2p Jos koodeja laskeva laskuri ei ole static, yksittäisten tarinoiden koodit eivät saa oikeita arvoja. Luokka- ja oliomuuttujien eron ymmärtäminen on Javassa olennaista. c) koodikenttä ei saa oikeita arvoja : -1p Satunnaiset ohjelmointivirheet, jotka aiheuttavat laskurin toiminnan epäonnistumisen. Ensimmäisellä arvolla ei ole merkitystä. d) koodikenttä ja laskuri sama muuttuja : -4p (jos tällainen vähennys, niin yo. vähennyksiä ei laskettu) Tällainen menettely aiheuttaa laskurin toiminnan täydellisen toimimattomuuden. e) muuttujien näkyvyys ei private : -2p Tehtävänannossa erikseen käskettiin muuttujat privaateiksi. Protectediksi muuttaminen oli virhe, sillä se ei ollut millään tapaa välttämätöntä b-kohdan tekemiselle. f) luokan tietorakenteiden esittely metodeissa, : -2p pelkästään esitellyn taulukon käyttäminen Tyypillinen virhe oli viittaaminen itse esiteltyyn taulukkomuuttujaan, jota ei oltu ikinä luotu. g) stringitaulukosta ei tehdä konstruktorissa aitoa kopiota : -2p Tehtävänannossa käskettiin estää Kansanrunon muuttaminen. Jos konstruktorin parametrina saama taulukko sijoitetaan suoraan muuttujaan, niin sen sisältöä voidaan edelleen muuttaa riippumatta siitä, onko taulukko määritelty final-avainsanalla. h) Aksessorit mikäOn... eivät toimi palauta oikeaa/mitään arvoa : -1p i) mikaOnKansanrunonRivi(...)-metodissa ei varauduta vuotoihin : -2p Tämä oli loppujen lopuksi ainoa virhetyyppi, johon tarvitsi varautua. Esim. parametrien null-arvot eivät aiheuttaneet pisteiden vähennyksiä. j) satunnaiset ohjelmointivirheet : -1p Ne satunnaiset ohjelmointivirheet, jotka kuitenkin voidaan aidoiksi virheiksi laskea, ei esim. sulun puuttuminen. Vähennykset tehtävään 1b: ----------------------- a) "extends Kansanruno" puuttuu : -2p Tätä virhettä ei löytynyt kuin parista paperista. Kyse on luultavasti huolimattomuudesta, mutta virheenä niin paha, että tästä sakotettiin. b) Kansanruno-luokan rakenteiden toistaminen : -4p Kansanrunon tietorakenteita ei ole mitään syytä toistaa. Myös Kansanrunon privaattikentät ovat periytyneet, niihin ei vain pääse käsiksi edes aliluokassa kuin julkisten aksessoreiden kautta. c) Kommentit-kenttä puuttuu : -3p d) konstruktori puuttuu : -3p Konstruktori ei periydy. e) super(...)-kutsu puuttuu, jos konstruktori oli : -2p Ne rakenteet, joihin ei itse päästä käsiksi, alustetaan yliluokan konstruktorin kutsulla. f) Pelkästään esitellyn taulukon käyttäminen (ei konstruoitu) : -2p g) yli- ja alivuotoihin ei varauduttu eri metodeissa : -2p h) tulostaKommentit()-metodissa tulostetaan : -2p null-kommenttirivit Tehtävänannossa käsketään tulostaa ei-tyhjät kommenttirivit. i) viittauksia Kansanrunon private-kenttiin : -3p Kaikkiin Kansanrunon privaattikenttiin tulee viitata aksessoreiden avulla. j) satunnaiset ohjelmointivirheet : -1p Arvostelussa ei ole tehty 1a-tehtävän kanssa toisteisia vähennyksiä. Esimerkkivastaukset: public class Kansanruno { private static int koodiLaskuri = 0; private final int koodi; private String[] runo; public Kansanruno(String[] rivit) { koodiLaskuri++; koodi = koodiLaskuri; runo = new String[rivit.length]; for (int i=0; i= 0 && rivi < mikäOnKansanrunonPituus()) { return runo[rivi]; } return null; } public void tulostaKansanruno() { for (int i=0; i < mikäOnKansanrunonPituus(); i++) { System.out.println("(" + i + ".) " + mikäOnKansanrunonRivi(i)); } } } public class KommentoituKansanruno extends Kansanruno { private String[] kommentit; public KommentoituKansanruno(String[] rivit) { super(rivit); kommentit = new String[rivit.length]; } public void liitäKommentti(String kommentti, int rivi) { if (rivi >= 0 && rivi < mikäOnKansanrunonPituus()) { kommentit[rivi] = kommentti; } } public String mikäOnKommentti(int rivi) { if (rivi >= 0 && rivi < mikäOnKansanrunonPituus()) { return kommentit[rivi]; } return null; } public void tulostaKommentit() { for (int i=0; i < mikäOnKansanrunonPituus(); i++) { if (kommentit[i] != null) { System.out.println("(" + i + ".) " + kommentit[i]); } } } }