Skip to end of metadata
Go to start of metadata

Harjoitukset sisältävät sekä esitehtäviä (tehdään ennen harjoituksia itsenäisesti) että harjoitustehtäviä (tehdään harjoituksissa ohjatusti).

Harjoitusten alussa käyn läpi ryhmän esitehtävät ja ohjaan harjoitusten tekemistä. Mikäli ryhmä on tehnyt sekä esitehtävät että harjoitustehtävät tyydyttävälle tasolle viimeistään harjoituksen loppuun mennessä, tästä tulee ryhmän jäsenille piste. Mikäli tehtävät jäävät selkeästi tekemättä tai kesken, tästä ei tule harjoituspistettä. 

Harjoitus 1

Harjoitus 1 ajoittuu viikolle 4 (21.-25.1.) Harjoitus sisältää sekä esitehtävän (tehtävä ennen harjoituksia) sekä harjoitusten aikana suoritettavan tehtävän.

Tehtävien tekemisessä kannattaa käyttää UML-editoria, esimerkiksi Visual Paradigm for UML.

Esitehtävä

Tutustu EasyCrypto -järjestelmän lähdekoodiin osoitteessa https://bitbucket.org/anttijuu/easycrypto/src/master/ 

Laadi UML:n luokkamalli järjestelmän sisältämistä luokista käyttäen UML:ää. Malleissa tulee näkyä

  1. luokat;
  2. luokkien perintäsuhteet;
  3. luokkien väliset assosiaatiot kardinaliteetteineen;
    1. pyri tunnistamaan assosiaation tyyppi: onko assosiaatio koosteassosiaatio (Car contains an (1) Engine), normaali assosiaatio (Owner owns (0..n) Car(s)) vai riippuvuusassosiaatio (Car uses Fuel).
  4. rajapintaluokat "tikkukaramelli" -notaatiolla esiteltynä.

Malleissa ei tarvitse näkyä:

  • jäsenmuuttujia;
  • luokkien metodeja;
  • standardikirjaston (STL) tai boost:n luokkia tai perustietotyyppejä (int, jne).

Mikäli koodin ja luokkamallien suhteet ovat sinulle vieraita tai olet epävarma, tutustu tähän demonstraatioon ja ota siitä mallia. Käytännössä luokkien löytäminen tapahtuu näin:

  1. etsi otsikkotiedostoista (.h, .hpp) class -avainsanoja – merkitse nämä luokiksi luokkamalliin
  2. perintäsuhteet löytyvät luokan esittelystä heti luokan nimen jälkeen; class B : public A { ... tarkoittaa sitä että luokka B on luokan A aliluokka (B perii A:n, B is-kind-of A).
  3. assosiaatiot löytyvät tutkimalla luokan jäsenmuuttujia: mikäli luokka B:llä on assosiaatio luokkaan C, silloin luokan B jäsenmuuttujana on luokan C instanssi (oliona, viittauksena (&) tai osoittimena *);
    1. heikompi riippuvuusassosiaatio (merkitään katkoviivanuolena) tarkoittaa että luokka B käyttää luokan C instassia johonkin ja tyypillisesti näkyy koodina siten että luokan B metodi saa parametrina luokan C olion ja kutsuu sen metodeja, mutta B:ssä ei välttämättä ole jäsenmuuttujaa joka on tyyppiä C.

Esittele laatimasi luokkamalli harjoitusten alussa opettajalle.

Harjoitustehtävä

Laadimme UML:n komponenttikaavion EasyCrypto -järjestelmästä.

  1. Tutustu järjestelmän elementtien CMake käännöstiedostoihin ja tunnistamme sieltä 
    1. mitä komponentteja kukin järjestelmän elementti tarvitsee ja
    2. minkä komponentin kunkin järjestelmän käännöstiedosto luo.
  2. Piirrä tämän perusteella UML:n komponenttikaavio EasyCrypto -järjestelmästä. Piirrä kaavioon myös komponenttien väliset riippuvuussuhteet ja komponenteille sen mahdollisesti sisältämät rajapinnat.
  3. Kunkin komponentin osalta, kerro miten komponentti sitoo (bind) käyttämänsä muut komponentit itseensä: käännösaikana, linkityksen aikana vai ajon aikana? 
  4. Lisätehtävä jonka voi tehdä jos ehtii: osita luokkakaavio Packageihin (UML:n kansiosymboli) ohjelmiston loogisen rakenteen mukaan. 

Esittele laatimasi komponenttikaavio opettajalle ennen harjoituksista poistumista.

Tässä malliratkaisu pdf-tiedostona ja Visual Paradigm -mallitiedostona.

Harjoitus 2

Harjoituksen aiheena viikolla 5 (28.1.-1.2.2019) on harjoitustyön aloitus.

Esitehtävät

Tässä vaiheessa pitäisi olla jo harjoitustyöryhmä kasassa. Jos ryhmää ei ole etkä halua tehdä työtä yksin, ryhmäytymistä siis on syytä jatkaa.

Tutustu harjoitustyön yleisiin tavoitteisiin ja vaatimuksiin. Jos näistä on jotain kysyttävää, voit kysyä harjoituksissa ja Moodlen keskustelualueella.

Hae harjoitustyösovellus tältä sivulta. Sivu sisältää myös ohjeet kääntämiseen. Voit jättää (ainakin aluksi) kääntämisen tekemättä, mutta hae ainakin harjoitustyösovelluksen lähdekoodi – tarvitset sitä tästä eteenpäin harjoituksissa ja itsenäisesti työskennellen.

Koska työ on aika laaja, ensimmäinen harjoitustyöhön keskittyvä esitehtävä on kevyttä YouTubeilua. Katso läpi neljä harjoitustyötä esittelevää videota.

Merkitse muistiin sellaisia asioita jotka mielestäsi liittyvät jotenkin mahdollisesti arkkitehtuuriasioihin. Muistele mitä luennoilla on ollut puhe tähän mennessä ja ovatko nämä asiat sovellettavissa tai nähtävissä videoilta. Kootkaa kukin omat muistiinpanonne yhteen paikkaan. Näistä voi olla myöhemmin hyötyä kun aloitatte varsinaisen arkkitehtuurisuunnitelma -dokumentin kirjoittamisen. Muistakaa että vaikka videoissa keskustellaan esim. tietyn kirjaston kääntämisestä, voin siellä kertoa asioita jotka myös liittyvät harjoitustyöhön ja arkkitehtuuriasioihin. Kannattaa siis katsoa ajatuksella kaikki videot vaikka ette aikoisi yrittääkään kääntää ja suorittaa harjoitustyösovellusta. Erityisesti viimeinen video on olennainen arkkitehtuurin kannalta monessakin mielessä, joten katsokaa ja tehkää muistiinpanoja.

Harjoitustehtävä

Harjoituksissa tehtäväksi jää vanha tuttu ensimmäisen viikon komponenttidiagrammin laatiminen, nyt harjoitustyöjärjestelmästä jota tästä eteenpäin kutsumme nimellä StudentPassing. Luo uusi UML-mallidokumentti Visual Paradigm:lla ja anna sille nimeksi StudentPassing.

Huomatkaa että tästä harjoituksesta eteenpäin teette kaikki eri UML-kaaviot tähän samaan UML-mallitiedostoon!

Tee komponenttikaavio perustuen StudentPassing:n CMakeLists.txt tiedostojen sisältöön. Tunnista siis järjestelmän komponentit ja komponenttien väliset riippuvuudet. Aloita BaseLayer -hakemistosta, sen jälkeen siirry StudentLayer -hakemistoon ja kolmanneksi tarkastele BasicInfoGUI -hakemistoa.

Kunkin komponentin oma nimi ja tyyppi (kirjasto tai sovellus) löytyy etsimällä CMakeLists.txt tiedostoista komentoa add_library tai add_executable. Etsi tietoa siitä mitä komponentteja kukin komponentti käyttää tai tarvitsee (vihje: etsi find_package -komentoja).

Kirjatkaa ylös mikä on käsityksenne kunkin komponentin roolista järjestelmän komponenttiarkkitehtuurissa. Miksi se on olemassa?

Harjoitus 3

Harjoituksessa viikolla 6 (4.2.-8.2.2019) keskitytään BaseLayer -nimiseen StudentPassing:n arkkitehtuurin elementtiin sekä UML:n käyttöönottokaavioon (deployment diagram).

Kaikki tämän harjoituksen mallit tehdään edellisessä harjoituksessa luotuun samaan UML-mallitiedostoon. Katso myös Visual Paradigm:n demovideo jossa vinkkejä työkalun käyttöön.

Esitehtävä

Rajoitumme tässä harjoituksessa tutkimaan vain BaseLayer-hakemiston luokkia. Laadi alustava luokkakaavio BaseLayer:ssa olevista luokista BaseLayer nimiseen UML-packageen käyttäen Visual Paradigm:ia:

  1. Luo uusi luokkamalli (class diagram) Diagram Navigator > Class Diagrams > right click > New class diagram
  2. Nimeä tämä luokkamallikaavio StudentPassing -nimiseksi ("pääluokkamalli")
  3. Lisää siihen UML:n package ("kansio" -symboli työkaluissa) nimeltään BaseLayer
  4. Klikkaa kansiota hiiren oikealla näppäimellä > valitse Subdiagrams > New Diagram... ja luo uusi Class diagram
  5. Laadi tähän uuteen luokkamalli-kaavioon luokkamalli jossa tulevat näkymään järjestelmän BaseLayer -hakemiston koodin perusteella tunnistetut
    • luokat 
      • ei jäsenmuuttujia, ei metodeja
    • rajapintaluokat (interface -stereotyypillä)
    • perinnät sekä rajapintojen (realizes -perintä) toteutukset
    • riippuvuudet (dependency), assosiaatiot (association) ja koosterakenteet (composition) BaseLayer:n muihin luokkiin ja rajapintoihin. 
      • älä kuvaa std kirjaston, boost -kirjaston tai muidenkaan kirjastojen luokkia tai assosiaatioita niihin
      • älä vielä katso mitä StudentLayer tai BasicInfoGUI:ssa on!

Aluksi voit luoda vaikka yhden luokan ja jatkaa myöhemmin. Varmista että ymmärrät näiden uusien kaavioiden väliset suhteet:

  1. Nyt kun palaat (vasemmalta Diagram Navigator > Class diagrams) tuohon "päätason" luokkamalliin (nimeltään StudentPassing), näet siellä tuon BaseLayer packagen eli kansion. 
  2. Klikkaa packagea nyt hiiren oikealla painikkeella > Subdiagrams. 
  3. Näet siellä tuon BaseLayer:n sisältämän luokkamallin valikossa ylimpänä. Klikkaa sitä. Näet BaseLayer:n sisällä olevan luokkamallin.

Näin voit helposti navigoida mallien hierarkian sisällä. Huomaa että voit aina palata Diagram Navigatorin kautta takaisin jonnekin muualle jos joudut mallien sisällä eksyksiin.

Tämän luokkakaavion täydentäminen jatkuu myöhemmissä harjoituksissa. Valmista ei siis tarvitse vielä tuottaa, kunhan kaavio saadaan hyvään alkuun. Esitehtävästä voi vielä puuttua luokkia, assosiaatioita jne. Olennaista on edetä sen verran että saatte harjoituksissa palautetta alustavaan malliin jota voitte sitten palautteen pohjalta kehittää eteenpäin.

Harjoitustehtävä

Tutustu erityisesti neljänteen demonstraatiovideoon. Vaikka demoa ajetaan havainnollistamisen helpottamiseksi yhdellä koneella, huomaa että ns. nodeja on tarkoitus oikeassa käyttötilanteessa ajaa kutakin omalla tietokoneellaan eri opettajien toimesta.

Piirrä käyttöönotto- eli deployment -kaavio, jossa näkyvät fyysiset laitteet (4 kpl) joilla demon "nodeja" ajetaan. Sijoita komponenttikaaviossa (tehtiin Harjoitus 2:ssa) olevat StudentPassing:n komponentit fyysisille laitteille.

Mieti ja kirjaa ylös seuraavia:

Katso BasicInfoGUI -kansiosta löytyvää bidialog.cpp -tiedostoa ja sen BIDialog::configureNode() -metodia. Täällä luotu ProcessorNode -luokan olio konfiguroidaan. Konfigurointiin käytetään konfigurointitiedostoa ja lisäksi nodeen lisätään "handlereitä".

Pohdittavaa: BasicInfoGUI on tuo käynnistyvä ohjelma jonka näet demovideolla, BIDialog on se luokka joka näkyy ikkunana painonappeineen. BasicInfoGUI auttaa käyttäjää käsittelemään opiskelijatietoja. Kun tutustuit BaseLayer -kansion luokkiin (mm. ProcessorNode), siellä ei kuitenkaan koodissa näy missään että käsiteltäisiin opiskelijatietoja. Mitä tämä tarkoittaa, miksi näin? Mitä tämä kertoo BaseLayer -kansiossa olevasta koodista jossa ProcessorNode.cpp:kin on?

Harjoitus 4

Harjoituksessa viikolla 7 (11.2.-15.2.2019) keskitytään StudentLayer -nimiseen StudentPassing:n arkkitehtuurin elementtiin sekä siihen miten muunneltavuutta tuetaan konfiguraatioilla.

Kaikki tämän harjoituksen mallit tehdään edellisessä harjoituksessa luotuun samaan UML-mallitiedostoon. Katso myös Visual Paradigm:n demovideo jossa vinkkejä työkalun käyttöön.

Muista kirjata kaikki arkkitehtuuriin liittyvät havainnot ja epäilykset ylös ryhmän omaan muistiinpanotiedostoon. Mieti koko ajan: miksi, mitä, miten. Erityisesti miksi on tärkeä kysymys.

Esitehtävä

Jos BaseLayer:n luokkamallin tekeminen on vielä kesken, jatka sen loppuun viemistä. Muista että jäsenmuuttujia eikä metodeja vielä tarvitse kirjata.

Aloita StudentLayer -kansion luokkakaavion tekeminen StudentLayer -packageen.

  1. Avaa ylimmän tason luokkamallikaavio StudentPassing ("pääluokkamalli") jonka teit harjoituksessa 3.
  2. Lisää siihen UML:n package ("kansio" -symboli työkaluissa) nimeltään StudentLayer
  3. Lisää perintäsuhde (kolmio): StudentLayer laajentaa BaseLayer -packagea.
    1. miksi perintä eikä riippuvuus (dependency)? Katsokaa StudentLayerin luokkia – suurin osa niistä perii jonkun BaseLayer:n luokan tai toteuttaa BaseLayer:n rajapinnan. StudentLayer siis laajentaa BaseLayerin toiminnallisuutta.
  4. Klikkaa StudentLayer -packagea hiiren oikealla näppäimellä > valitse Subdiagrams > New Diagram... ja luo uusi Class diagram
  5. Laadi tähän uuteen luokkamalli-kaavioon luokkamalli jossa tulevat näkymään järjestelmän StudentLayer -hakemiston koodin perusteella tunnistetut luokat ja assosiaatiot sekä perinnät että assosiaatiot ja riippuvuudet, kuten harjoituksessa 3 teit BaseLayer:n kanssa.

Löydät StudentLayer:stä myös luokkia jotka perivät (inherits) BaseLayer:ssä olevan luokan, tai toteuttavat (realizes) BaseLayer:ssä olevan rajapinnan. Samoin StudentLayer:ssä olevat luokat käyttävät BaseLayer:stä kotoisin olevia luokkia (näkyvät jäsenmuuttujina ja parametreina metodeissa jotka ko. BaseLayer -olioita käyttävät).

Älä tee BaseLayerissä olevasta yläluokasta tai rajapinnasta uutta luokkaa StudentLayer -packageen (koska luokka on jo olemassa BaseLayer:ssä), vaan 

  1. Avaa Visual Paradigm:n Diagram navigator (tai Model navigator) ja raahaa ja pudota (drag & drop) BaseLayer:ssä oleva (ylä)luokka/rajapinta StudentLayer:n luokkakaavioon
  2. Käytä perintä (rajapinnan toteutus) -työkalua ja kuvaa perintäsuhde StudentLayer:ssä olevan ja BaseLayer:stä tuodun luokan välille, jos sellainen on.
  3. Käytä assosiaatio tai riippuvuus -työkalua ja kuvaa assosiaatio tai "käyttösuhde" StudentLayer:ssä olevan ja BaseLayeristä tuodun luokan välille, jos sellainen on.

Kun klikkaat StudentLayer:n luokkakaaviota hiiren oikealla napilla jostain tyhjästä kohtaa missä ei ole mitään mallielementtiä, tulee esiin valikko. Valitse Presentation options > Class display options > Show name only. Nyt näet StudentLayer:n luokkakaaviossa BaseLayer:stä tulleiden luokkien nimen alla suluissa sen packagen jossa luokka on määritelty. Mallin lukija pystyy nyt näkemään miten StudentLayerin luokat liittyvät BaseLayerin luokkiin ja kuitenkin näkyy myös selkeästi se, mistä kukin luokka on "oikeasti kotoisin".

Älä tuo metodisesti kaikkia BaseLayer -luokkia StudentLayer -luokkakaavioon – tuo vain sellaiset luokat joita StudentLayer:n luokat perivät tai käyttävät. Tarkoitus ei ole tosiaan kaikkea mahdollista tuoda; vain se mitä StudentLayer:n luokat todella tarvitsevat BaseLayer:stä.

BaseLayer ja StudentLayer:n luokkakaavioita jalostetaan eteenpäin harjoitusten edetessä. Tärkeintä tässä vaiheessa on saada luokat, perinnät, rajapintojen toteutukset ja assosiaatiot kaavioihin. Yksityiskohtia tarkennetaan myöhemmin.

Harjoitustehtävä

Harjoituksessa keskitytään konfigurointiin ja muunteluun arkkitehtuurillisena ominaisuutena StudentPassing:ssa.

Näit demovideoissa useassakin paikassa miten käyttäjä voi konfiguroida järjestemän toimintaa käynnistysparametrilla. Lisäksi kun teit koodista luokkamalleja, näit useassakin luokassa sanan "configuration". Harjoituksen 3 aikana tutustuit myös siihen mistä konfigurointi "alkaa", eli BasicInfoGUI:n BIDialog::configureNode(). Lisäksi olet nähnyt videoilla miten solmut käynnistetään parametrilla (konfigurointitiedoston nimi), ja mitä kaikkea konfigurointitiedostoissa voidaan konfiguroida. Tehtävä:

  1. Listaa eri elementit (tiedostot, luokat, paikat koodissa (metodit), jne.), mitkä liittyvät järjestelmän konfigurointiin.
  2. Kuvaa mitä eri asioita järjestelmässä voidaan konfiguroida ja millä mekanismilla ja missä vaiheessa järjestelmän käynnistymistä / suorittamista. 
  3. Kuvaa nämä muunneltavat asiat ei-toiminnallisina vaatimuksina.
    1. Lisää nämä ei-toiminnalliset vaatimukset tunnistenumerolla tai -koodilla varusteltuna ryhmänne muistiinpanodokumenttiin.
  4. Älä unohda miettiä ja kirjata ylös onko järjestelmässä muita kuin konfiguraatiotiedostoon perustuvia muuntelun mekanismeja.

Tässä vaiheessa kun luokkamallit BaseLayer:stä ja StudentLayer:stä ovat jo pitkällä, tulisi selvitä myös se, miten BaseLayer ja StudentLayer liittyvät toisiinsa ja mikä arkkitehtuuriin liittyvä merkittävä ratkaisu StudentPassin:iin sisältyy. Tästä keskustellaan harjoituksissa ja pyritään löytämään vastaus joka dokumentoidaan ryhmän muistiinpanoihin.

Myöhemmin kun aloitat järjestelmän arkkitehtuurin suunnitteludokumentin täydentämisen, nämä tiedot tulevat sinne kukin omaan lukuunsa. Kuvaa asiat siis selkeästi niin että itse myöhemmin ymmärrät mitä tuli kirjoitettua ja joku toinenkin ymmärtää. Dokumentoi siis jotakuta tuntematonta lukijaa varten; selkeästi, perustellen. Ajatuksena pitäisi olla se, että tämä tekemäsi dokumentaatio kertoo softakehittäjälle, mitä kaikkea hänen pitää tehdä että saa uuden tekemänsä noden toteutuksen konfiguroinnin menemään oikein; eräänlainen käyttöohje siis.

Viimeinen askel: täydennä laatimaasi StudentPassing:n komponenttikaaviota lisäämällä sinne komponenttina konfiguraatiotiedosto(t), jotka tunnistit konfiguraation analyysin myötä. Valitse komponentille oikea stereotyyppi. Osoita mitkä järjestelmän muista komponenteista käyttävät tätä konfiguraatiokomponenttia ja piirrä vastaavat riippuvuudet komponenttikaavioon. Olet myös huomannut että konfiguraatiotiedostojen lisäksi sovellus käyttää datatiedostoja. Lisää myös nämä komponenttikaavioon (stereotyypillä <<file>>) sekä molemmat tiedostot myös käyttöönottokaavioon (deployment diagram), siten että käyttöönottokaaviosta näkyvät nyt kaikki ne tiedostot ja komponentit joita vaaditaan ja tarvitaan StudentPassing:n noden suorittamisessa.

Harjoitus 5

Harjoituksessa viikolla 8 (18.2.-22.2.2019) keskitytään jatkamaan luokkamallien tekemistä ja kuvataan järjestelmän ajonaikaista arkkitehtuuria ja sen sisältämää rinnakkaisuutta.

Esitehtävä

Jatka BaseLayer ja StudentLayer -elementtien luokkamallien tekemistä. Erityisesti mieti nyt tarkemmin luokkien välisten assosiaatioiden luonnetta. Varsinainen tämän kerran esitehtävä (alla) liittyy ajonaikaiseen arkkitehtuuriin (process view).

Ensin taustaa. Ajonaikainen arkkitehtuurin selvittäminen ja kuvaaminen alkaa siitä ymmärryksestä, että jokainen suoritettava ohjelma ajetaan omassa prosessissaan. Prosessin sisällä suoritettava koodi pystyy käsittelemään prosessin sisällä olevaa dataa eli on muistin suojauksen yksikkö. Prosessin pääsäie luodaan prosessille aina automaattisesti, ja on koodin suorituksen yksikkö

Jokaisessa ohjelmassa eli prosessissa on siis aina vähintään yksi säie (ns pääsäie, main thread) jossa kaikki koodi suoritetaan peräkkäisesti. Jos halutaan rinnakkaisesti "erillään" suoritettavaa koodia, on koodissa explisiittisesti luotava uusia ns. toissijaisia säikeitä (secondary threads). Toinen mahdollisuus on käyttää kirjastoissa olevaa koodia jotka mahdollisesti säikeitä käyttäessään rinnakkaisuuden toteuttamiseksi, piilottavat sisäänsä sen että jossain koodia suoritetaan omassa säikeessään. Tämä ei näy kirjastoa käyttävälle sovellukselle ja sen koodille.

Toissijaisia säikeitä tarvitaan usein kun:

  • ohjelma käsittelee suuria määriä tietoa, käsittely kestää kauan ja halutaan antaa käyttäjälle mahdollisuus käyttää ohjelmaa muihin tarkoituksiin. Jos käsittely tehdään pääsäikeessä, ohjelma jumittuu käyttäjän näkökulmasta käsittelyn ajaksi. Käytettävyystutkimuksissa on todettu että käyttäjä ei useimmiten huomaa alle 200ms jumituksia, joten jos käsittely kestää enempää kuin tuon, olisi harkittava jotain rinnakkaisen suorituksen mekanismin, esim. säikeiden käyttöä. Muitakin ratkaisuja on toki olemassa. Luodaan ja käynnistetään siis toinen säie joka prosessoi datan ja ilmoittaa jotenkin pääsäikeelle kun käsittely on tehty, ja pääsäikeessä ilmoitetaan asiasta käyttäjälle.
  • ohjelma käyttää ns. blokkaavia toimintoja. Esimerkiksi pyydetään socket -oliota (tietoliikennejuttuja...) lukemaan verkosta dataa (socket.read()). Jos dataa ei tule, read blokkaa pääsäikeen suorituksen ja odottaa dataa tulevaksi, eli käyttäjä ei taaskaan voi tehdä mitään. Siksi usein edellytetään että blokkaavia palveluita käytetään erillisestä säikeestä. Luodaan siis toinen säie jossa kutsutaan socket.read() jolloin pääsäie voi jatkaa käyttäjän palvelemista. Esimerkiksi Android -käyttöjärjestelmässä yrityskin käyttää verkko-ohjelmointia pääsäikeestä johtaa ohjelman kaatamiseen. Android framework on siis erityisesti rakennettu estämään edes yrittämästä verkko-operaatioita pääsäikeestä käsin.
  • jne.

Esitehtävänä on etsiä ja listata ne paikat StudentPassing -järjestelmästä, jossa luodaan ja käytetään säikeitä. Järjestelmä luo säikeitä käyttäen C++:n standardikirjaston (STL) std::thread -luokkaa. Etsi siis koodista kaikki ne paikat joissa kyseistä luokkaa käyttäen luodaan uusi säieolio (etsi koodista siis tekstiä "std::thread").

Käytämme prosessointiarkkitehtuurin esittämiseen komponenttikaaviota, jossa komponentit ovat nyt (kirjastojen ja ohjelmien sijaan) prosesseja, säikeitä ja lisäksi olioita jotka luovat ("sisältävät", "hallitsevat") näitä säieolioita.

Täydennä alla oleva UML:n deployment -kaavion esimerkkiä noudattaen omaa kaaviotasi siten että 

  1. lisää kaavioon jokainen tunnistamasi säie komponentiksi (näitä pitäisi koodista löytyä 4 kpl);
  2. valitse komponentin stereotyypiksi <<thread>> (löytyy Edit stereotypes -valikosta)
  3. lisää kaavioon koosteassosiaatio säikeeseen: jos ProcessorNode luo säikeen, piirrä siitä koosteassosiaatio ko. säiekomponenttiin (ProcessorNode contains threadXxx).
  4. jos säie löytyy jostain muusta kuin ProcessorNode -komponentista, piirrä ko. luokka komponentiksi kaavioon ja samaan tapaan piirrä koosteassosiaatio kaavioon.

 

Tee kaavio niin valmiiksi kuin pystyt, harjoituksissa sitten katsotaan onko korjattavaa tai täydennettävää.

Vilkaise säikeiden koodia ja yritä päätellä mitä säikeet tekevät. Tästä ei tarvitse saada täyttä ymmärrystä, sillä varsinaisessa harjoitustehtävässä kuvataan sitten opettajan ohjauksessa säikeiden toimintaa UML:n aktiviteettykaavioilla (Activity Diagram). Kertaa siis esitehtävän tekemisen jälkeen UML:n activity diagram:n notaatio ja käy läpi jokunen esimerkki mitä verkosta tai aiempien kurssien materiaaleista löytyy.

Harjoitustehtävä

Luo jokaiselle säiekomponentille, jonka teit esitehtävässä, UML:n activity diagram. Klikkaa Visual Paradigm:ssa säiekomponettia hiiren oikealla painikkeella, valitse Subdiagrams > Add new diagram > Activity Diagram.

Kuvaa aktiviteettikaaviossa säikeen toiminnallisuus. Säikeen toiminnallisuus näkyy koodina joko siinä yhteydessä missä säie luodaan (xxxthread = new std::thread() { .... }) tuossa neljän pisteen sijasta, tai säiefunktiossa joka säikeen luomisen yhteydessä mainitaan. Opettaja neuvoo tässä alkuun mikäli koodin tulkinta ei tahdo onnistua.

Lisäksi harjoituksissa kuvataan omassa aktiviteettikaaviossaan, miten ProcessorNode::start() -metodissa käynnistetään siellä olevat rinnakkaiset säikeet eli aktiviteetit.

Kaikkia aktiviteettikaavioita ei tarvitse harjoituksissa tehdä, osa saa jäädä itsenäisesti tehtäväksi harjoitustyön osaksi.

Tilannekatsaus

Täältä löytyy nyt yhteenvetoa ja mallia sekä apuja siihen missä tilanteessa harjoituksissa ja harjoitustyön kanssa nyt pitäisi suurin piirtein olla.

Harjoitus 6

Harjoituksen kuusi (viikolla 9; 25.2.-1.3.2019) teemana on a) hajautettujen komponenttien välinen viestintä, b) tiedon konvertointi ulkoisesta muodosta (verkko, tiedostot) sisäiseen (oliot) ja sisäisestä muodosta ulkoiseen sekä c) virheiden käsittely. Sekä hajautus että virheiden käsittely ovat esimerkkejä arkkitehtuurin concern:eista eli huolenaiheista (kts. Johdanto -luennon kalvot 49-51). Nämä concernit on myös suunniteltava mukaan arkkitehtuuriin ja siksi tämä harjoitus kohdistuu nimenomaan tällaisiin koko arkkitehtuurin läpitunkeviin huolenaiheisiin.

Esitehtävän tekemistä jatketaan harjoitustyön tekemisen merkeissä itsenäisesti, joten nämä vastaukset voivat olla vielä vaillinnaisia. Huolehtikaa kuitenkin siitä että harjoituksiin tullessa teillä on tarpeeksi materiaalia jotta ohjauksen kautta pääsette varmasti kohti sellaista kuvausta joka riittää harjoitustyössä hyväksyttävään kuvaukseen.

Esitehtävä

Yritysjärjestelmäpatternit -luennolla puhuttiin siitä kuinka yritysjärjestelmissä tarvitaan muuntaa tietoa formaatista toiseen. Syynä se että eri sovellukset joita on yritykselle aikoinaan kehitetty ja aiotaan integroida toisiinsa luennoilla esiteltyillä tavoilla, sisältävät kukin oman tietomallinsa ja tietoformaattinsa (tietokanta, teksti- tai binääritiedosto, JSON, XML tai jotain muuta). Nämä tietomallit eivät ole yhteensopivia toistensa kanssa. Kun sitten integroidaan yritysjärjestelmiä toisiinsa, suunnitellaan ns. kanoninen tietomalli joka on sovellusriippumaton esitys siitä miten tietorakenteet ja formaatit esitellään ja toteutetaan.

Vaikka StudentPassing ei ole tällainen järjestelmä, se on silti hajautettu ja hajautettujen komponenttien kommunikoinnissa komponentin sisäiset tietorakenteet ja -formaatit on muunnettava ulkoiseen muotoon verkossa siirtämistä varten. StudentPassing:ssa sisäinen kanoninen tietomuoto on binäärinen; StudentDataItem -luokka (ja sen yläluokka DataItem) sisältävät tietorakenteet joilla nodet (komponentit) sisäisesti käsittelevät opiskelijatietoja. Ulkoiseksi, tiedon siirtoa varten valituksi esitysmuodoksi on valittu JSON.

StudentPassing:ssa siis nodet käsittelevät opiskelijatietoja, ja kun noden käsittely on valmis, se muuntaa opiskelijatiedon binäärisestä oliomuodosta JSONiin. Tämä JSON-muotoinen viesti lähetetään verkon yli seuraavalle nodelle. Kun seuraava node ottaa dataa vastaan, se muuntaa JSONina esiteltyn datan sisäiseen oliomuotoon käsittelyä varten.

Tutki ja dokumentoi miten StudentPassing:n eri tietokoneille hajautetut komponentit viestivät toistensa kanssa. Mitä pitäisi dokumentoida - vastaa seuraaviin kysymyksiin tutkimalla BaseLayerin ja StudentLayerin koodia (*.cpp ja *.h):

  1. mitä internetin protokollaa käyttäen tietoa siirretään?
  2. mitkä luokkamallin luokat vastaavat tiedon siirrosta verkosta/verkkoon?
    1. erittele missä luokat sijaitsevat (base vai student).
  3. mitä StudentPassing:n ulkopuolisia kirjastoja käytetään verkkotiedonsiirron toteutuksessa?
  4. mikä on tiedon siirron formaatti
  5. minkälaisia viestejä komponentit lähettävät toisilleen verkon yli?
  6. mitä StudentPassing:n ulkopuolista kirjastoa käytetään konversion toteutuksessa?
  7. mitkä luokkamallin luokat (BaseLayer & StudentLayer) vastaavat verkossa tapahtuvan tiedon siirron formaatin käsittelystä (sovelluksen sisäisestä formaatista ulkoiseen konvertointi ja takaisin)?
  8. missä vaiheessa/paikassa käynnistyy konversio ulkoisesta esitysmuodosta sisäiseen esitysmuotoon?
  9. missä vaiheessa/paikassa käynnistyy konversio sisäisestä esitysmuodosta ulkoiseen esitysmuotoon?

Olennaista on siis tunnistaa luokkien vastuita (responsibility) liittyen tähän hajautukseen – miten hajautukseen liittyvät vastuut sijoittuvat arkkitehtuuriin?

Komponenttien välisten viestien esimerkkejä löydät StudentPassing:n bitbucketissa olevasta dokumentaatiosta sekä (jos pystyt ajamaan ohjelmia itse) kaikkien solmujen logitiedostoista. Voit katsoa myös tätä malliesimerkkiä logitiedostosta, jossa näet myös näitä viestejä joita komponentit saavat ja lähettävät, tulostettuna logiin.

Käy samalla tavalla läpi myös tiedostojen kanssa tapahtuvaa tiedonsiirtoa (tiedosto >> sovellus, sovellus >> tiedosto):

  1. mitkä luokkamallin luokat vastaavat tiedon siirrosta tiedostoista sovellukseen ja takaisin tiedostoihin?
    1. erittele luokat BaseLayer:ssä ja toisaalta StudentLayer:ssä
  2. mikä on tiedon siirron formaatti?
    1. tähän lisätietoa InstalledFiles -hakemiston README.md:stä.
  3. mitä tietoja tiedostoista luetaan/kirjoitetaan?
  4. missä vaiheessa/paikassa käynnistyy konversio ulkoisesta esitysmuodosta sisäiseen esitysmuotoon?
  5. missä vaiheessa/paikassa käynnistyy konversio sisäisestä esitysmuodosta ulkoiseen esitysmuotoon?

Kuvaa nämä tekstinä suunnitteludokumentaatioonne. Tarvittaessa voitte täydentää tekstiä selittävillä kuvilla. Huomatkaa että tuosta hajautukseen liittyvien kysymysten vastauksista (kohdat 1, 4, 5) syntyy myös StudentPassing -ohjelman protokollan kuvaus. Protokolla kuvataan suunnitteludokumenteissa yleensä omana erillisenä lukunaan.

Harjoitustehtävä

Harjoitustehtävässä keskitytään esitehtävän eteenpäin ohjauksen lisäksi virheiden käsittelyyn arkkitehtuurissa. Ennenkuin aloitat, varmista että käytät viimeisintä versiota koodista – virheiden käsittelyä on hieman muutettu tätä tehtävää ajatellen keskiviikkona 6.2. Hae siis tuorein versio bitbucketista.

Aluksi taustaa... Virheiden syyt ovat moninaiset. Kaikenlaista voi aina mennä pieleen; vaadittava tiedosto voi puuttua, sen sisältö voi olla vääränmuotoista tai tietoja puuttua. Verkosta saapuva data voi olla korruptoitunutta, vääränlaista tai vaikka pahantahtoisesti lähetettyä väärää dataa. Jos halutaan tehdä todella luotettavasti toimiva ohjelma, suunnittelijan ja koodarin tulisi ottaa asenteeksi se, että mikä tahansa rivi koodia voi periaatteessa aiheuttaa virheen eli poikkeuksen. Kaikkiin mahdollisiin ongelmiin tulisi varautua jotenkin.

Tämä on kuitenkin väärä tapa: 

Väärä tapa käsitellä virheitä

Jos doSomething() aiheuttaisi poikkeuksen, koodi jatkaa kuitenkin suoraan eteenpäin suorittamaan askelta nextStep(). Mutta jos doSomething() epäonnistui, luultavasti tuo objekti olisi nullptr eli oliota ei saatu luotua – silti jatketaan eteenpäin seinään ajon jälkeen niinkuin mitään ei olisi tapahtunut! Erittäin todennäköisesti nextStep():iä ei voida suorittaa koska edeltävä askel jo epäonnistui. Ylipäätään virheen käsittelyn periaate ei voi olla se, että virheestä huolimatta jatketaan eteenpäin.

Suunnittelijan ja koodarin (suunnittelijakoodarin) on mietittävä millä tasolla virhe on järkevintä käsitellä ja miten. Yllä olevan esimerkin virheenkäsittely voisi olla itse asiassa vaikkapa näin:

Ehkä parempi tapa virheen käsittelyyn

Eli ehkä tässä tapauksessa paras tapa on jättää virheet startDoingSomethingComplex:n sisällä käsittelemättä ja siirtää virheen käsittely ko. metodin ulkopuolelle. Näin metodin sisällä mahdollisesti tapahtuvat poikkeukset käsitellään ylemmällä tasolla. Joskus käsittely siirretään jopa esim. johonkin main -funktioon tai vastaavaan korkean tason paikkaan.

Tässä vaiheessa on hyvä muistuttaa että virhe voidaan ilmaista poikkeusten lisäksi myös esim. funktion paluuarvolla (0 = homma onnistui, muut arvot virhekoodeja, tai false = virhe ja true on onnistuminen), tai vaikkapa globaalina virhemuuttujana. Tässä harjoituksessa keskitytään vain poikkeuksilla heitettyihin virheisiin ettei hommasta tulisi turhan työlästä.

Sovelluksen pitäisi siis aina vähintäänkin tarkistaa että ulkopuolelta saatu data (verkko, tiedostot, käyttäjän syöttämä data) on varmasti oikeellista ja jos näin ei ole, käsitellä tämä virhetilanteena. Sovelluksen pitäisi kuitenkin toimia virheistä huolimatta; se ei saa kaatua vaan keskeyttää virhellisen datan käsittely ja vähintään ilmoittaa käyttäjälle ongelmasta. Virheiden käsittelyn sijoittaminen sopiviin ("oikeisiin") paikkoihin arkkitehtuurissa on siis olennainen suunnittelupäätös.

Harjoitustehtävänä on etsiä kaikki paikat koodista jossa käsitellään (try / catch -lohkot) poikkeuksia (exception). Etsi siis try -avainsanoja koodista. Lisäksi, tutki tiedostoja käsittelevää koodia (data- tai konfiguraatiotiedostoa luetaan) ja pohdi, miten koodi toimisi jos esim. tiedostoa ei olekaan olemassa koneella jossa ohjelmaa ajetaan.

Olennaista on ymmärtää miksi virheiden käsittely on arkkitehtuurissa juuri näissä paikoissa? Miten nämä virheiden käsittelyn paikat liittyvät sovelluksen datan käsittelyyn (verkosta saapunut tai tiedostoista luettu data)? Jos käy kuten tuossa edellä kuvattiin ja tiedostoista luettu ja/tai verkosta tuleva data on virheellistä, miten ohjelma toipuu tilanteesta?:

  1. Jos verkosta tullut data on virheellistä (ei vastaa suunniteltua datan sisältöä/rakennetta), mitä sen käsittelyssä tapahtuu? 
  2. Jos tiedostosta tullut data on virheellistä, mitä sen käsittelyssä tapahtuu?
  3. Jos joku Handlereistä aiheuttaa virheen (poikkeuksen) kun datapaketteja (Package) käsitellään, mitä tapahtuu?
  4. Entä jos konversio ohjelman sisäisestä muodosta (olio) ulkoiseen (tiedosto tai verkkoon lähetettävä data) epäonnistuu, mitä tapahtuu?

Mieti näissä tilanteissa, kaatuuko ohjelma, saako käyttäjä virheilmoituksen, mitä tapahtuu virheelliselle datalle? Jatketaanko virheellisen datan käsittelyä vai ei? Miten ylipäätään ohjelma jatkaa eteenpäin vai jatkaako (kaatuu tms)?

Dokumentoi StudentPassing:n virheiden käsittelyn sijoittamisen periaatteet arkkitehtuurimuistiinpanoihinne:

  1. missä virheet käsitellään ja miksi siellä?
  2. miten sovellus käyttäytyy jos verkosta tuleva data on virheellistä?
  3. miten sovellus käyttäytyy jos tiedostosta luettu data on virheellistä tai tiedostoa ei ole?
  4. miten virheiden käsittelypaikat liittyvät edellisen tehtävän prosessointiarkkitehtuuriin eli ajonaikaiseen arkkitehtuuriin?

 

Viikko 10 ei harjoituksia

Ei harjoituksia tässä viikolla 10.

Harjoitus 7

Harjoituksen seitsemän (viikolla 11; 11.3.-15.3.2019) teemana on suunnittelumallit (design patterns) ja dynaamiset mallit (sekvenssikaaviot).

Esitehtävä

Alla on luettelo suunnittelumalleista linkkeineen wikipediasivulle jossa lisätietoa kyseisistä suunnittelumalleista. Voit myös kerrata kurssin luentomateriaalista suunnittelumalleja. Osa näistä suunnittelumalleista on käytössä StudentPassing:n arkkitehtuurissa, osa ei.

Käy läpi tekemänne luokkamallit (BaseLayer ja StudentLayer, tutki myös BasicInfoGUI:n koodia) ja selvitä mitä suunnittelumalleista ohjelmistoon on toteutettu, mitä ei. Kannattaa myös katsoa koodia, lähinnä luokkien otsikkotiedostoja (kommentteineen) kun selvität näitä asioita.

Katso aina yhden suunnittelumallin esittämää luokkarakennetta ja tutustu suunnittelumallin tarkoitukseen. Sen jälkeen katso luokkamallejanne ja mieti löytyykö vastaava rakenne luokkamallista. Varmista koodiin tutustumalla, onko luokkamalli kenties toteutettuna StudentPassingiin vai ei.

Suunnittelumallikandidaatit:

  1. Prototype
  2. Strategy
  3. Message queue (katso myös luento koneenohjausjärjestelmien suunnittelumalleista)
  4. Model-View-Controller (katso myös luento suunnittelumalleista) 
  5. HeartBeat  (katso myös luento koneenohjausjärjestelmien suunnittelumalleista)
  6. Factory method
  7. Composite
  8. Template method

Kirjaa ylös ne suunnittelumallit muistiinpanoihinne jotka ovat toteutettuna StudentPassingiin. Kirjaa myös arvelemasi suunnittelumallin käyttötarkoitus arkkitehtuurissa. Muistele luentoa ohjelmistoarkkitehtuurien suunnitteluprosessista (Jan Boschin malli) – suunnittelumalleja käytetään ei-toiminnallisten vaatimusten toteuttamiseksi. Niillä on siis tarkoitus. Kirjaa ylös mitä ei-toiminnallista vaatimusta suunnittelumalli voisi toteuttaa.

Jos mielestäsi jossain käytetään jotain suunnittelumallia jota tässä ei luetella, voit nekin kirjata ylös. Tai jos saat jonkun idean arkkitehtuurin parantamiseksi jollakin suunnittelumallilla, voit senkin kirjata ylös ideaksi arkkitehtuurin parantamiseksi.

Huomio

Icon

Observer -suunnittelumallia ei StudentPassing:ssa käytetä. Koodissa olevat Observer -päätteiset rajapintaluokat eivät ole osa Observer design patternia. Sitä ei siis kannata esittää suunnittelumalliksi.

Harjoitustehtävä

Harjoitustehtävässä keskitytään kuvaamaan ohjelmiston käyttäytymistä sekvenssikaavioilla. Muistele sekvenssikaavioiden kuvauksen perusteita aikaisemmilta kursseilta, kurssimateriaaleista sekä netistä. Voit halutessasi kuvata asiat myös communication diagrammilla. Sekvenssi- ja kommunikaatiodiagrammien ero on lähinnä visuaalinen. Sekvenssikaaviossa aika (== viestien lähettämisjärjestys) kulkee ylhäältä alas "elämänlankaa" pitkin, kun taas kommunikaatiokaaviossa viestien lähettämisjärjestys näytetään viestien numerointina. Suosittelen sekvenssikaaviota jossa viestien järjestys on helpompi esittää ja sitä muuttaa, ja lukeminen on myös selkeämpää layoutin ansiosta. Muista että sekvenssikaavio on yleensä esimerkinomainen, se kuvaa tietyn tyypillisen tilanteen. Usein samasta toiminnallisuudesta voidaan piirtää useitakin sekvenssejä – normaali tilanne, poikkeustilanne ja vaikkapa virheellinen tilanne joka näyttää miten virheet pitäisi käsitellä. Harjoituksessa riittää yhden tilanteen kuvaaminen per tapahtuma.

Katso kurssin wikistä demonstraatio koodin ja interaktiodiagrammien (sekä luokkamallin) välisistä suhteista.

Harjoitusten aluksi opettaja demonstroi sekvenssikaavioiden piirtämistä yhden valmiin sekvenssikaavion avulla. Kaikkia alla olevia sekvenssikaavioita ei tarvitse saada valmiiksi harjoituksissa, vaan ne tehdään loppuun itsenäisesti osana harjoitustyön tekemistä.

Huomaa että kun luot sekvenssikaavion Visual Paradigm:lla

  • Voit tuoda sekvenssiin osallistuvia olioita lifeline:ksi aikaisemmin tekemistäsi luokkamalleista (BaseLayer, StudentLayer) drag & dropilla. 
    • Avaa vasemmalle diagram navigator tai model explorer ja raahaa sieltä luokka olioksi sekvenssikaavioon.
  • Jos luokkamalleissa ei ole sopivia oliota, voit joko...
    • tehdä luokkamalliin uusia luokkia (BaseLayer, StudentLayer), tai
    • tehdä uusia luokkamalleja (BasicInfoGUI), johon lisäät tarvittavan/-t luokat
  • ...jonka jälkeen voit tuoda uuden/-t luokan olioksi sekvenssikaavioon.
  • ...tai luoda olion työkalupaletista (lifeline -työkalu) sekvenssikaavioon määrittelemättä vielä sen luokkaa.

Paras vaihtoehto on tuoda valmis luokka sekvenssikaavioon lifelineksi eli elämänlankaolioksi. Tällöin kun olio lähettää toiselle viestin, voit valita viestiksi jo valmiina oliossa mahdollisesti olevan metodin.

Kuvaa seuraavat tapahtumat karkealla tasolla sekvenssikaavioilla. Virheenkäsittelyä tai poikkeustilanteita ei tarvitse kuvata; keskitytään siihen mitä tapahtuu jos kaikki sujuu hyvin, ilman tarkistuksia ja muita yksityiskohtia jotka voi jättää koodarin huolehdittavaksi.

 

Ensimmäinen tapahtuma

Lähtötilanne on seuraava: verkosta saapuu paketti käsiteltäväksi. Sekvenssikaavio lähtee liikkeelle tilanteesta jossa NetworkReader on saanut paketin verkosta. Tämä on siis NetworkReader.cpp:n rivillä 110:

Kun viesti saapuu

Piirrä sekvenssikaavio olioiden välisestä yhteistoiminnasta aina siihen pisteeseen asti kun paketti (Package) on saatu käsiteltyä Handlereiden toimesta. Handlereiden sisällä tapahtuvaa käsittelyä (DataHandler::consume()) ei tarvitse kuvata.

LISÄYS 14.3.: Kuvatkaa vain datapaketin käsittely – Package::Control -tyyppisten pakettien käsittelyä ei tarvitse kuvata. Näin ei tarvitse kuvata ollenkaan miten Control -paketti (komennot) lähetetään eteenpäin. Käytännössä siis  if (package.getType() == Package::Control -lauseiden sisälle ei tarvitse edes vilkaista.

LISÄYS 2 14.3.: Tässä vähän apua noihin hankaliin paikkoihin...

Toinen tapahtuma

Piirrä sekvenssikaavio olioiden välisestä yhteistoiminnasta kun BasicInfoGUI käynnistyy, alkaen BIDialog -luokan olion luomisen loppuvaiheista (BIDialog.cpp, rivi 45 alkaen). Sekvenssikaaviossa ei tarvitse kuvata käyttöliittymäolioiden kanssa puuhastelua; keskitytään kuvaamaan miten ProcessorNode luodaan ja konfiguroidaan. Kuvaa jonkun konfiguraation mukaisen Noden (esim. "ExamInfoConfig", valitse itse minkä) luominen esimerkkinä, kaikkia konfiguraatioita ei tarvitse kaavioon piirtää. Sekvenssin "suorittamisen" jälkeen Noden pitäisi olla valmis käynnistettäväksi Start -napin painalluksella. Tämä käynnistyminenhän on jo kuvattu aktiviteettidiagrammeilla harjoituksessa 5.

Kolmas tapahtuma

Piirrä sekvenssikaavio tilanteesta jossa käyttäjä painaa käyttöliittymässä Ping -nappia, aina siihen asti että ping -viesti on lähetetty seuraavalle nodelle ja ping -viestin lähetyksestä on kerrottu käyttäjälle. Oletetaan että seuraava node on (Writer on olemassa) ja että viestijonossa ei ole muita paketteja lähetettävänä.

Tilanne käynnistyy siis BIDialog.cpp:n onPingButtonClicked -metodista:

Ping -nappia painettu

Ja päättyy sekä kohtaan a) NetworkWriterin säie menee lepotilaan (wait) ja siihen että b) käyttöliittymässä lukee "Ping sent to next node (if any).".

Harjoitus 8

Harjoituksen kahdeksan (viikolla 12; 18.3.-22.3.2019) teemana on dokumentaation aloittaminen arkkitehtuurisuunnitelman dokumenttipohjaan esimerkkidokkarin avulla. Lisäksi viimeistellään ja tarkistetaan edellisten tehtävien UML-mallit ja niiden kuvaukset Arkkitehtuurisuunnitelma -dokumenttiin

Esitehtävä

Ladatkaa arkkitehtuurin dokumentaation pohjaksi esimerkkidokumentti. Muokatkaa dokumenttia*) oman ryhmänne malliseksi; kirjoittajat, versiointi jne. Poistakaa esimerkkisisältö (jättäkää lukujen otsikot) ja alkakaa täyttämään lukuja omista muistiinpanoistanne joihin tähän mennessä olette kirjanneet havaintonne edellisten harjoitusten ja oman työskentelyn myötä. Jos muistiinpanonne ovat ranskalaisia viivoja ja ytimekkäästi kuvattuja avainsanoja ja epätäydellisiä lauseita, kirjoittakaa teksti auki niin että se on

  • hyvää kieltä
  • selkeästi kirjoitettua kieltä
  • on ymmärrettävissä ryhmänne ulkopuoliselle lukijalle joka ei tunne StudentPassing:ia.

Muistakaa että dokumentaation tarkoitus on kommunikoida, olla muistin tuki, lisätä ymmärrystä. Mikä on epäselvästi ja vajaasti viestitty, ei ole ymmärrettävissä tai on väärin ymmärrettävissä. Nämä ongelmat viestinnässä johtavat bugeihin, vääriin toteutuksiin, puuttuviin toteutuksiin ja ylipäätään kaikenlaiseen turhaan härdelliin ohjelmistokehityksessä.

Muistakaa myös, että kirjoittaminen – asian ulkoistaminen omasta mielestä - on myös hyvä tapa lisätä omaa ymmärrystä. Kirjoittaessa voi huomata ettei itse asiassa asia olekaan selvä edes itsellensä – näin asiaa tulee sitten ajateltua ja toivottavasti sitä kautta ymmärrys lisääntyy. Sitä kautta on sitten helpompi taas ulkoistaa sitä mitä kirjoittamisen kautta ymmärsi. Dokumentaation kirjoittaminen on siis iteratiivinen prosessi samalla tavalla kuin ohjelmistokehitys ylipäätään.

*) Dokumentti kannattaa laittaa verkkoon, esimerkiksi Google Driveen tai johonkin wikiin (miksei vaikkapa wiki.oulu.fi). Näin sen editointi, pääsyoikeuksien rajoitus ja jakaminen (myös opettajalle arvostelun ja kommenttien antamisen kannalta) on helpompaa. Lisäksi dokumenttiin liitetyt kuvat (kts. Harjoitustehtävä alla) on helppo linkittää itse dokumenttiin. 

Harjoitustehtävä

Jatkakaa dokumentin täydentämistä lisäämällä siihen kuvina sopiviin ja oikeisiin paikkoihin tekemänne UML-mallit ja muut tekemänne mallit ja kuvat jotka eivät välttämättä ole UML:ää. Näitä muita mallikuvia voivat olla esimerkiksi muuntelua ja variaatiota kuvaavat mallit (kts. luentomateriaali variaatiosta ja variaatiopisteistä). Useat mallit ovat aivan liian laajoja ja sisältävät pientä piiperrystä (tekstiä ja kuvaelementtejä) jota dokumentin sivulta ei voi hyvin nähdä. Sijoittakaa siis kaikki kuvat paitsi dokumenttiin (copy-paste), laittakaa dokumenttiin kuvan yhteyteen myös linkki netissä olevaan kuvatiedostoon jota voi zoomata ja tarkastella paremmin kuin dokukmenttiin upotettua kuvaa.

Muistakaa että UML-mallit voivat muuttua vielä suunnittelun edetessä ja malleja korjailtaessa ja täydentäessä. Miettikää siis kuvien linkitys ja upottaminen siten että niitä on helppo muokata ja täydentää.

Huolehtikaa myös siitä että ne tunnistamanne ei-toiminnalliset vaatimukset jotka StudentPassing (erityisesti BaseLayer) toteuttaa, on selkeästi tunnistettu, kirjoitettu auki ja selitetty dokumentissanne. Tätä auttaa ymmärtämään tutustuminen DDirWatcher -järjestelmään joka on myös rakennettu BaseLayer:n päälle. Sen avulla voitte tunnistaa muuntelua, variaatiota, uudelleenkäytettävyyttä jne. tukevia rakenteita ja ominaisuuksia BaseLayerissä. Nämä asiathan liittyvät kiinteästi ja olennaisesti ei-toiminnallisiin vaatimuksiin.

Tämän harjoituksen päättyessä dokumentaation pitäisi olla viimeistelyä vailla valmis hyvässä kuosissa muttei vielä valmis, opettajan antaman palautteen pohjalta. Dokumentaatiota voidaan viimeistellä aina harjoitustyön deadlineen saakka.

Muistakaa kuitenkin että dokumentti ja siihen liittyvät mallit ovat harjoitustyön olennainen osa ennen uusien vaatimusten esittämistä harjoitustyön vaiheessa 2 (joka alkaa harjoituksen 9 myötä). Se miten pystytte selittämään, mallintamaan ja kuvaamaan StudentPassing:n arkkitehtuuria ja siihen liittyviä ei-toiminnallisia vaatimuksia ja niiden suunnittelu- ja toteutusratkaisuja on kurssin arvostelun kannalta merkittävää sisältöä. Panostakaa siis selkeään hyvin kirjoitettuun tekstiin ja tekstiä hyvin tukeviin ja selitettyihin mallielementtien dokumentointiin.

Harjoitus 9

Tutustutaan uusiin vaiheen II vaatimuksiin. Pohditaan kunkin vaatimuksen kohdalla miten arkkitehtuuria muuntamalla vaatimus saadaan toteutettua. Pohditaan ATAM-luennoilla esitettyyn tyyliin, miten vaatimukset ja niiden ratkaisut vaikuttavat toisiinsa.

Voidaan valita kussakin ryhmässä joku vaatimus mitä yhdessä pohditaan, tai sitten ryhmät itse päättävät missä järjestyksessä ja mitä vaatimuksia lähtevät kehittämään.

Harjoitus 10

Jatketaan uusien vaatimusten suunnittelua arkkitehtuuriin. Opettaja konsultoi ja kommentoi.

Harjoitus 11

Jatketaan uusien vaatimusten suunnittelua arkkitehtuuriin. Opettaja konsultoi ja kommentoi.

Harjoitus 12

Jatketaan uusien vaatimusten suunnittelua arkkitehtuuriin. Opettaja konsultoi ja kommentoi.

Harjoitus 13

Jatketaan uusien vaatimusten suunnittelua arkkitehtuuriin. Opettaja konsultoi ja kommentoi. Harjoitusten päättymisen jälkeen on vielä n. kuukausi aikaa viimeistellä dokumentaatio ja mallit.

 

 

  • No labels