: Työtavat ja ohjeet

Yleistä

Työskentelytavoista

Harjoitustyön aikana toteutetaan itsenäisesti esim. joku peli (laivanupotus, miinaharava, tetris, ...) tai kortisto-ohjelma (tyyliin laskuharjoitustehtävien Olutmuistio tai Ilmoittautumisjärjestelmä hieman laajennettuna). Ohjelmalle tehdään dokumentaatio.

Ohjelman tekoprosessissa noudatetaan hyviä ohjelmistotuotannon käytänteitä:

  • ohjelman toiminnallisuutta kasvatetaan iteratiivisesti eli joka viikko toteutetaan jotakin ohjelman toiminnallisuutta koko ajan laajentaen
  • dokumentaatiota (Javadoc ja luokkarakenne) pidetään koko ajan ajan tasalla
  • ohjelmakoodin testaus automatisoimaan JUnit-testauskehyksen avulla

Kaikeen listalla mainittuun annetaan ohjeistusta harjoitustyön kuluessa ja kasvavassa määrin tällä sivulla.

Harjoitustyötä voi tehdä itsenäisesti kotona tai hyödyntää pajatunteja. Vaadimme kuitenkin, että työ etenee viikoittain suunnitelman mukaan. Kaikkien on edistyttävä alla luetellun aikataulun mukaan tehden viikottaiset tehtävät.

Jos joku asia on epäselvää, kysy välittömästi opettajalta.

Viikoittaiset tehtävät
 

1. viikko

  • aiheen kuvaus, ks. alla kohta Dokumentaatio, osa1/tehtävämäärittely
  • Junit-tehtävät, ks. kohta Testaus
  • aloitetaan ohjelmointi, ks. kohta Ohjelman toteutus
  • vähintään 10 testitapausta omaan ohjelmaan
  • Ohjelman rakenteen kuvaaminen, ks. kohdat Dokumentaatio, osa 2/Ohjelman rakenteen kuvaaminen 

2. viikko

  • tarkistetaan että jokainen käyttää versionhallintaa
  • ohjelma selvästi edennyt
  • JavaDoc
    • jokaiselle luokalle luokan kuvaus
  • testitapaukset
    • testitapauksia tulee tehdä vähintään luokkien lukumäärä * 4, jokaiselle sovelluslogiikan luokalle tulee olla testitapauksia
    • jos ohjelman luokkien määrä on hyvin suuri, ei viikon 2 testitapausten määrän tarvitse ylittää viittäkymmentä
    • jokaisen luokan testit tulee määritellä omassa testiluokassa. Yhtä luokkaa kohti saa olla myös useita testiluokkia 
  • dokumentaatio: luokkakaavion tarkentaminen
    • päivitetään luokkakaavio vastaamaan ohjelman tämän hetkistä rakennetta
    • ks. Ohjelman rakenteen kuvaaminen/miniUML:Luokkarakenteen kuvaaminen/viikko 2
  • dokumentaatio: toiminnallisuuden kuvaaminen
    • luonnostellaan muutamaa tärkeimpää toiminnalisuutta vastaavat sekvenssikaaviot
    • ks. Ohjelman rakenteen kuvaaminen/miniUML:Toiminnallisuuden kuvaaminen

 3. viikko

  • ohjelma selvästi edennyt
  • JUnit
    • testitapauksia kaikille uusille luokille
    • testitapauksia vähintään 6 kpl / luokka, yhteenlaskettu määrä vähintään 50
    • triviaaleille luokille ei tarvita kuutta testitapausta, monimutkaisille luokille taas voi tehdä enemmänkin kuin 6 testitapausta
  • JavaDoc pidetään ajantasalla, ruvetaan kuvaamaan metodeja
  • dokumentointi
    • luokkakaaviot ja sekvenssikaaviot ajan tasalla
  • koodi siistiksi
    • luokkien, metodien, attribuuttien, parametrien ja  muuttujien nimentä selkeäksi ja johdonmukaiseksi
      • nimien siis tulee olla mahdollisimman kuvaavia 
      • huom: tee uudelleennimeäminen NetBeansin Refactor/rename-ominaisuuden avulla, ks täältä kohta refaktorointi
    • ei liian pitkiä metodeja
      • metodin pituuden tulee ilman erittäin hyvää syytä olla korkeintaan 15-20 riviä
      • tätä pitemmän metodit tulee jakaa useampiin metodeihin
    • ei copy-pastea
      • jos koodissa on useassa kohdassa samaa koodia, tulee luoda metodi, joka sisältää jaetun koodin, tai joissain tapauksissa yliluokka, joka sisältää kahden eri luokan yhteiset koodit

 4. viikko

  • ohjelman edelleenkehitys samaan tapaan kuin edellisellä viikolla

 5. viikko

  • ohjelman edelleenkehitys samaan tapaan kuin edellisellä viikolla

 6. viikko

  • pakollinen oman työn demoaminen omalle ryhmälle (5 min.)

Työn palautus

  • ohjeet työn palautusta varten
  • palautus tehdään sähköpostilla oman ryhmän ohjaajalle viimeistään viikon päästä viimeisestä oman ryhmän palaverista
  • palautetussa versiossa kaavioiden, JUnit-testitapausten, Javadoc:in ja muun dokumentoinnin on oltava ajantasalla

Viikkotehtävien tarkistus

Viikkotehtävät tarkistetaan aina seuraavan viikon tiistaina tai torstaina (harjoitusryhmien jaottelun mukaan) ohjelmointipajassa B121, lukuunottamatta viimeistä missä työ palautetaan kokonaisena. 

Dokumentaatio, osa 1


Tehtävämäärittely

Kirjoitetaan lyhyt kuvaus toteutettavasta ohjelmasta. Kuvaus tarkentuu myöhemmin, aluksi on dokumentoidaan vaan ne ideat joiden pohjalta työtä lähdetään tekemään.

Kuvaus sisältää muutaman tekstikappaleen yleiskuvauksen, tyyliin:

Aihe: ilmoittautumisjärjestelmä

Toteutetaan järjestelmä jonka avulla ylläpidetään tietojenkäsittelylaitoksen kurssitietoja sekä tietoja kursseille ilmoittautuneista opiskelijoista...

Tämän lisäksi listataan ranskalaisin viivoin järjestelmän tarjoama toiminnallisuus:

käyttäjät: opiskelija ja opetushallinto

opiskelijan toiminnot:

  • järjestelmään kirjautuminen
    • onnistuu jos salasana ja käyttäjätunnus oikein
  • kaikkien kurssien listaus
  • ilmoittautuminen
    • onnistuu jos kurssi ei ole täynnä ja opiskelija ei ole jo kurssilla
  • omien ilmoittautumisten listaus
  • tietyn kurssin ilmoittautujien listaaminen


opetushallinnon toiminnot:

  • järjestelmään kirjautuminen
    • onnistuu jos salasana ja käyttäjätunnus oikein
  • uusien kurssien lisäys
  • ...

koska molemmilla käyttäjillä samoja toimintoja, ne olisi kannattanut yhdistää

kaikkien käyttäjien toiminnot:

  • ...

    
Kuvauksen ei tarvitse olla hirveän pitkä eikä kattava. Kuva siitä mitä ohjelmistolta halutaan, tulee tarkentumaan pikkuhiljaa.

Ohjelman toteutus


Toteutus siis etenee "iteratiivisesti ja inkrementaalisesti". Tämä tarkoittaa sitä, että heti alussa toteutetaan pieni osa ohjelman toiminnallisuudesta, esim. ilmottautumisjärjestelmässä olisi luonnollista toteuttaa ensin kirjautuminen. Ohjelman ydin pidetään koko ajan toimivana ja uutta toiminnallisuutta lisätään pikkuhiljaa. 

Saattaa olla, että kun uutta toiminnallisuutta lisätään, huomataan, että jotain jo ohjelmaan toteutettua täytyy muuttaa tai parannella. Muutoksia ja parannuksia pitääkin tehdä rohkeasti. Omaa koodia ja sen rakennetta pitää parantaa jatkuvasti.

Iteratiiviseen tapaan tehdä ohjelma liittyy kiinteästi automatisoitu testaus josta puhutaan seuraavassa kohdassa. Aina uutta lisättäessä täytyy näet varmistua, että kaikki vanhat ominaisuudet toimivat edelleen. Kaiken testaaminen käsin uudelleen ja uudelleen ei ole ajankäytöllisesti järkevää.

Ohjelman rakenteen suhteen kannattaa ottaa mallia laskuharjoitusten viikkojen 5 ja 6 Ilmo-tehtävästä (katso tehtävämäärittelyt ja tarvittaessa mallivastaukset), sen tekstuaalisesta ja Graafisesta versiosta. Kuten Ilmo, on oma ohjelma toteutettava ehdottomasti niin, että sovelluslogiikka (esim. Ilmossa luokat Kayttajatietokanta, Ilmo ja Kurssi) erotetaan täysin käyttöliittymästä. Ilmo:n tapaan sovelluslogiikan on hyvä olla sellainen, että käyttöliittymä voidaan helposti vaihtaa ilman että muuhun sovellukseen olisi tehtävä paljon muutoksia.

Kannattanee pyrkiä siihen, että ohjelmassa on paljon pieniä, selkeävastuisia luokkia, ja että ohjelman kokonaislogiikka toteutuu näiden luokkien yhteistyönä. Ilmo-tehtävä toimii tässäkin suhteessa hyvänä esimerkkinä.

Omaan sovellukseen voidaan tehdä aluksi tekstikäyttöliittymä, tai vaihtoehtoisesti suoraan graafinen käyttöliittymä. Graafisen käyttöliittymän ohjelmoiminen käsin on hyvin työlästä ja voi olla parempi käyttää NetBeansiin integroidun Swing GUI -builderin käyttöä. Tällöin projektia luodessa tulee valita Java Desktop Application.  Lisätietoa GUI-builderistahttp://netbeans.org/kb/docs/java/gui-functionality.html

Testaus


Automatisoitu testaus on pakollista ja siihen opastetaan ohjauksissa.  Kokeile tehdä testejä tämän ohjeen mukaan.

Ensimmäisellä viikolla siis jokaisen on käytävä läpi linkin takana oleva teksti.

Omaan alustavaan toteutukseen on pakko tehdä ainakin 10 JUnit-testitapausta ensimmäisen viikon aikana.

Huomaa, että jotta sovelluslogiikan testaus voidaan automatisoida, on sovelluslogiikka erotettava käyttöliittymästä kuten edellisenssä luvussa todetaan.

Dokumentaatio, osa 2


Javadoc

Ohjelmakoodi kommentoidaan Javadoc:in avulla. Ks. esim. http://en.wikipedia.org/wiki/Javadoc ja
http://java.sun.com/j2se/javadoc/writingdoccomments/

Tarkemmat ohjeet JavaDocin käyttöön

Ohjelman rakenteen kuvaaminen

Ohjelman/suunnitelman rakenne tullaan kuvaamaan tarpeellisella tasolla. 

Kuvauksessa tulee olla 

  • luokkarakenne
  • hahmotelma ydintoiminnallisuuksista
  • käyttöliittymän näkymien välinen navigaatiorakenne

Kaksi edellistä esitetään "tuopinalustaan piirrettynä miniUML:na", käyttäliittymän navigaatiorakenne vapaamuotoisena kuvan ja tekstin sekotuksena

Koska ohjelman rakenne kasvaa ja muuttuu ajan myöstä, käy samoin ohjelman rakenteen kuvaukselle. Tämän takia rakenne hahmotellaan käsin tuopinalustoihin tai papereille. Ohjelman lopulliseen dokumentaatioon tehdään tarpeen vaatiessa luokkarakenteen kuvaus jollakin piirto-ohjelmalla.

UML (Unified modeling language) on graafinen kuvauskieli joka soveltuu ohjelman luokkarakenteen sekä toiminnallisuuden kuvaamiseen. UML-kieltä opiskellaan kurssilla Ohjelmistojen mallintaminen. Seuraavassa käydään läpi muutama UML:n perusrakenne, jotka riittävät javalabran dokumentoinnin tarpeisiin.

miniUML: Luokkarakenteen kuvaaminen

viikko 1:

Luokka kuvataan laatikkona jossa on kolme osaa:

luokan nimi
attribuutit
konstruktorit
metodit

Koska Javadoc kuvaa attribuutit ja metodien nimet, kannattaa useimmiten ne jättää merkitsemättä luokkarakenteen kuvauksessa ja kuvata luokat pelkkinä laatikkoina joissa on luokan nimi. Muutaman toiminnallisuuden kannalta oleellisen metodin voi toki luokkalaatikkoon merkitä.

Ensimmäisellä viikolla meille riittää hyvin yksinkertainen luokkarakenteen kuvaus. Eli jokaisesta luokista oma laatikko ja jos luokkien tai luok    kien mukaisten olioiden välillä on yhteys, tulee laatikoiden välille viiva. Viivalle voi merkitä mitä yhteys tarkoittaa. Seuraavassa esimerkkinä Ilmo-järjestelmän hyvin yksinkertainen kuvaus. Laskareissa opiskelijat olivat pelkkiä merkkijonoja. Oletetaan nyt, että opiskelijoita edustaa oma luokka Opiskelija. 

viikko 2:

Tarkennamme edellisellä viikolla aloitettua ilmo-järjestelmän luokkakaaviota. Huomaamme, että edellisen viikon kuvaan piirretyt yhteydet eivät vastaa täysin koodissa olevia yhteyksiä.Koodissa nimittäin Ilmo-luokan olio ei tunne Käyttäjatietokanta-oliota, siispä niiden välille ei tule yhteyttä. Alla on tarkennettu kuva. Yhteyksiin on nyt lisätty suuntia jaosallistumisrajoitteita.

Muutamia huomioita luokkakaaviosta. Laatikot siis edustavat luokkia. Yhteydet eli viivat laatikoiden välillä taas (pääosin) edustavat olioiden välisiä yhteyksiä. Luokista Ilmo, Kayttajatietokanta ja Tekstikayttoliittyma on kustakin olemassa ohjelmassa yksi olio, kaikki Main:in luomia. Main ei ole itsessään olio, sen toiminta tapahtuu staattisen pääohjelmametodin public static void main()-sisällä, Mainin voi kuitenkin ajatella luokkakaaviossa samaan tapaan olioksi kuin esim. Ilmon. Kurssi-olioita ohjelmassa taas on monia, samoin Opiskelija-olioita (todellisuudessa Opiskelija-luokkaa ei ohjelmassa ollut mutta kuvittelemme että näin olisi).

Osallistumisrajoitteista:

Kayttajatietokanta-olioon liittyy useita Opiskelija-olioita, mutta yksi Opiskelija-olio taas liittyy täsmälleen yhteen Kayttajatietokantaan. Tämän takia luokkien välille tulevaan yhteysviivaan tulee 1 Kayttajatietokannan päähän ja * Opiskelijan päähän:

Merkintä * siis tarkoittaa montaa.

Yhteen Kurssi-olioon liittyy monia Opiskelija-olioita, tämän takia yhteyden Opiskelijan päähän merkitään *. Koska yksi Opskelija-olio voi osallistua monelle Kurssille, tulee yhteyden Kurssin päähän myös *. Eli kurssille voi osallistua monta opiskelijaa, opiskelija voi osallistua monelle kurssille.

Main tuntee vain yhden Ilmon ja Ilmoon liittyy vain yksi main, siksi molemmissa päissä on 1.

Yhteyksien suunnista:

Huomaamme, että esim. Tekstikayttoliittyma:n ja Ilmo:n väliseen yhteyteen on merkitty nuolenkärki Tekstikayttoliittyma:Sta Ilmo:on päin. Tällä korostetaan sitä seikkaa, että Tekstikayttoliittymä-olio tuntee Ilmo-olion, mutta Ilmo-olio ei tunne Tekstikayttoliittyma-olioa. Tämän voi tarkistaa Ilmo:n koodista. Yhteyden suunta merkitään vain jos suunnalla on sovelluksen kannalta merkitystä.

miniUML: Toiminnallisuuden kuvaaminen

Ei riitä, että kuvaamme luokkarakenteen. Luokkarakenteesta ei nimittäin käy millään lailla ilmi miten ohjelman toiminnallisuus on toteutettu. 
Toiminnallisuudella tarkoitetaan suurinpiirten samaa kuin yllä tehtävämäärittelyssä listattuja ohjelman tarjoamia toimintoja, esim. Ilmottautumisjärjestelmässä 

  • järjestelmään kirjautuminen
  • kurssille ilmoittautuminen
  • ohjelman alustustoimet

Ohjelma toteuttaa toiminnallisuutensa olioidensa välisen yhteistyön avulla. Eli eri oliot kutsuvat toistensa metodeja siten, että haluttu toiminto saadaan aikaan. Toiminnallisuutta voidaan kuvata UML:n ns. sekvenssikaavion avulla. 

Sekvenssikaavio listaa oliot, jotka osallistuvat tiettyyn toiminnallisuuteen sekä olioiden väliset metodikutsut siinä järjestyksessä kun ne tapahtuvat.

Oliot on listattu yleensä kaavion ylälaitaan. Mukana voi olla myös käyttäjää edustava tikku-ukko. 

Kirjautuminen

Kuvataan ensin miten ilmojärjestelmään kirjautuminen tapahtuu. Toiminnallisuuteen osallistuvat käyttäjä (tikku-ukko), Main ja Tekstikäyttöliittymä- sekä Ilmo-oliot. Kaaviossa aika etenee alaspäin. Kunkin laatikkona kuvatun olion alapuolella on viiva, joka kuvaa ajan etenemistä viivaan liittyvän olion kannalta.

Toiminnallisuus alkaa sillä, että Main kutsuu tekstikäyttöliittymän metodia sisaankirjautuminen, tama on kuvattu nuolena Mainista Tekstikayttoliittymään.  Kutsu saa aikaan sen, että Tekstikayttoliittyma pyytaa käyttäjätunnusta ja salasanaa. Käyttäjän vastaukset on kuvattu katkoviivana. Katkoviivana on kuvattu myös se kun tekstikäyttöliittymä palauttaa Main:ille nimen ja salasanan.

Metodikutsut siis kuvataan tavallisena nuolena ja paluu metodista katkoviivanuolena. Tulostus käyttäjälle voidaan tarvittaessa merkitä metodikutsun tapaan.

Seuraavaksi Main kutsuu Kayttajatietokannan metodia kirjaudu, parametrina käyttäjätunnus ja salasana. Kuvatussa tilanteessa kirjautuminen onnistuu, ja metodi palauttaa true. Seuraavaksi Main kutsuu Ilmon metodia kayttajaKirjautui, parametrina käyttäjätunnus.

r

Ilmottautuminen kurssille

Toisena esimerkkinä sekvenssikaavio, joka kuvaa käyttäjän ilmoittautumisen kurssille. Nyt kaavioon on merkattu useita Kurssi-olioita, joista kurssi2:n oletetaan edustavan käyttäjän valitsemaa kurssia.

Toiminta alkaa sillä, että Main pyytää Tekstikäyttöliittymää näyttämään päävalikon. Päävalikko tulostetaan käyttäjälle. Käyttäjän tekemä valinta palautetaan Main:ille.  Main kutsuu tekstikäyttöliittymän metodia listaaKurssit tekstikäyttöliittymä pyytää kurssilistausta Ilmo:lta metodilla getKurssilista ja tulostaa kurssilistan ruudulle. Seuraavaksi Main kutsuu Tekstikayttoliittyman metodia ilmoittauduKurssille, käyttäjän valinta palautetaan Main:ille, joka kutsuu Ilmon: metodia ilmoittaudu, parametrina käyttäjän valitsema kurssi. Ilmo taas kutsuu valitulle kurssille metodia ilmoittaudu, parametrina kirjautuneen käyttäjän nimi.

Ohjelman alustus: Uusien olioiden luomisen merkintätapa

Jos oliot syntyvät ohjelman kuluessa, niitä ei merkitä yläreunaan vaan vasta sille kohdalle missä ne luodaan.
Seuraavassa esimerkki ohjelman alustustoimista. Ensin Main luo Ilmo-olion, sitten Tekstikayttoliittyma-olion joka saa konstruktorissa parametrina viitteen luotuun Ilmoon. Lopulta luodaan Kayttajatietokanta. Kun Main kutsuu Ilmo:n metodia lisaaKurssi, luo Ilmo uuden Kurssi-olion.

Sekvenssikaavioilla kannatta kuvata vain ohjelman tärkeimmät toiminnalisuudet. 

Toiminnallisuuden nopea luonnostelu sekvenssikaavioina ennen ohjelmointia on erittäin hyödyllistä, näin voin nopeasti kartoittaa mitä osia toiminnallisuudesta kannattaa laittaa minkäkin olion vastuulle.

Lisää UML:ää

Jos kiinnostusta riittää, UML-kieleen voi tutustua proaktiivisesti Ohjelmistojen mallintaminen-kurssin luentokalvojen avulla. Luokkarakenteen mallintamisesta puhutaan luennoilla 3, 4, 5 ja 7. Toiminnallisuuden mallintamisen kannalta hyödyllinen on luento 6.

Miten ja milloin rakennetta ja toiminnallisuutta tulee kuvata?

Luokkarakenteen ja toiminnallisuuden kuvaamisen ja ohjelmoinnin tulee edetä käsi kädessä. Ensin suunnitellaan hieman ohjelman rakennetta ja toiminnallisuutta piirtelemällä luonnoksia tuopinalustoille. Sen jälkeen ohjelmoidaan suunilleen suunnitelman mukaan. Yleensä kuitenkin käy niin, että ohjelmoidessa huomataan, että tuopinalustaan piirretyt suunnitelmat eivät ole kaikin osin järkeviä ja ohjelmoitu toteutus onkin hiukan erilainen. Se ei haittaa. Kun taas suunnitellaan ohjelmaa hiukan pidemmälle, otetaan uusi tuopinalusta ja lähtökohdaksi otetaan toteutuksen nykytilanteen mukainen ohjelman rakenne.

Erityisesti toiminnallisuuden luonnostelu sekvenssikaavioina ennen ohjelmointia on hyödyllistä, näin voin nopeasti kartoittaa mitä osia toiminnallisuudesta kannattaa laittaa minkäkin olion vastuulle.

Tuopinalustoille ja suttupapereille tapahtuva suunnittelu ja ohjelmointi siis etenevät iteratiivisessa ohjelmiston toteuttamistavassa käsi kädessä.

Kun ohjelma on valmis, voi ohjelman rakennetta ja toiminnallisuutta kuvata tarvittaessa tarkemmin, piirto-ohjelmalla (tai UML-editorilla) piirrettävin kuvin. Liian tarkka kuvaaminen esim. luokkien suhteen ei ole tarpeen jos ohjelmasta tehty Javadoc ajaa saman asian.

Käyttöohje

Lopussa kirjoitetaan ohjelmalle käyttöohje.