Ohjelmistotuotanto

Oppilasrekisteriesimerkki

Tämä esimerkki näyttää, miten oppilasrekisterin toiminnallinen määrittely etenee tekniseksi määrittelyksi. Samalla se havainnollistaa, miten kaavioita tehdään Mermaidilla. Kuvattu sovellus on tarkoituksella yksinkertaistettu, jotta määrittelyjen ja kaavioiden yhteys on helppo nähdä.

Sivua voi käyttää myös oman määrittelyn oppaana: kuvaa ensin tarve ja vaatimukset, havainnollista niitä sopivilla kaavioilla ja suunnittele vasta sitten toteutus. Kaikki projektit eivät tarvitse kaikkia tässä esitettyjä kaavioita. Valitse ne, jotka auttavat ymmärtämään juuri oman järjestelmäsi toimintaa tai rakennetta. Kaavioiden Mermaid-koodit voi avata niiden alta.

Dokumenttien otsikointi

Vaatimusmäärittelylle ja tekniselle määrittelylle ei ole yhtä kaikkialla käytettyä alaotsikkorakennetta. Organisaatiolla, asiakkaalla tai oppilaitoksella voi olla oma dokumenttipohjansa. Tässä esitetty otsikointi on yksi mahdollinen tapa jäsentää sisältö. Sovella rakennetta projektin tarpeisiin ja mahdolliseen annettuun dokumenttipohjaan. Olennaista on, että tarvittavat asiat kuvataan selkeästi ja ristiriidattomasti.

Tässä ohjelmoijien opetukseen tarkoitetussa oppaassa käytetään myös kaavioiden nimiä otsikkoina, jotta kaaviotyypit ja niiden esimerkit löytyvät helposti. Samalla opit yhdistämään kaavion nimen sen tarkoitukseen. Voit käyttää omassa dokumentissasi samaa tapaa tai nimetä luvut käsiteltävän asian mukaan. Otsikkoa voi myös täsmentää, esimerkiksi ”Käyttöönottokaavio : sovelluksen sijoittuminen”, ”Viestiyhteyskaavio : kirjautuminen” tai ”Luokkakaavio : Qt-sovelluksen rakenne”.

Kerro kaavion yhteydessä lyhyesti, mitä se kuvaa juuri tässä järjestelmässä, ja selitä tarvittavat ratkaisut ja perustelut. Kaikkien alaotsikoiden ei tarvitse olla kaavioiden nimiä: esimerkiksi tavoitteet ja rajaus, hyväksymiskriteerit sekä rajapintojen kuvaukset tarvitsevat myös sanallista käsittelyä.

Määrittelyvaihe (Vaatimusmäärittely)

Toiminnallinen määrittely kuvaa asiakkaan ja käyttäjän näkökulmasta, mitä järjestelmän pitää tehdä. Tässä vaiheessa kuvataan toiminnot ja käyttöliittymän perusidea ilman teknisiä toteutusvalintoja.

Vaatimusmäärittely on tätä laajempi kokonaisuus: siihen kuuluvat myös tavoitteet, rajaus, käyttöoikeudet, laatuvaatimukset ja hyväksymiskriteerit. Kaaviot täydentävät sanallisia vaatimuksia. Ne eivät yksin kerro esimerkiksi sitä, kuka saa nähdä henkilötiedot tai miten onnistunut toteutus todetaan.

Tavoite, käyttäjät ja rajaus

Aloita kertomalla, mikä ongelma ratkaistaan ja keitä ratkaisu palvelee. Tämän esimerkin tavoitteena on, että opiskelija voi tarkistaa omat tietonsa ja ilmoittautua kursseille itsenäisesti. Käyttäjä on opiskelija; oppilaitos puolestaan määrittelee, mitä tietoja ja kursseja palvelussa tarjotaan.

Tässä rajauksessa mukana ovat kirjautuminen, omien henkilötietojen ja arvosanojen katselu sekä kurssille ilmoittautuminen. Arvosanojen syöttäminen, opiskelijatietojen ylläpito ja maksaminen jäävät esimerkin ulkopuolelle. Oletuksena on, että opiskelija-, kurssi- ja suoritustiedot ovat jo olemassa. Kirjaa vastaavat oletukset omaan määrittelyysi ja varmista ne tilaajalta.

Vaatimukset ja hyväksymiskriteerit

Anna tärkeille vaatimuksille tunnisteet, jotta niihin voi viitata suunnittelussa ja testauksessa. Kirjoita jokainen vaatimus niin täsmällisesti, että sen toteutuminen voidaan todentaa. Hyväksymiskriteeri kertoo, millä havaittavalla tuloksella vaatimus katsotaan täytetyksi.

  • V-01: Opiskelija saa nähdä vain omat arvosanansa. Hyväksymiskriteeri: kirjautunut opiskelija näkee omat suorituksensa, eikä toisen opiskelijan tietojen pyytäminen palauta tämän arvosanoja.
  • V-02: Opiskelija voi ilmoittautua tarjolla olevalle kurssille. Hyväksymiskriteeri: onnistunut ilmoittautuminen tallentuu ja opiskelija saa vahvistuksen; tallennuksen epäonnistuessa näytetään virheilmoitus.
  • L-01: Arvosanojen katselun tulee olla riittävän nopeaa. Esimerkki mitattavasta tavoitteesta: vähintään 95 prosenttia arvosanahauista valmistuu kahdessa sekunnissa 50 samanaikaisen käyttäjän testissä. Kuormitus, tietomäärä ja mittausympäristö sovitaan ennen testausta.

Laatuvaatimuksia voivat olla myös käytettävyys, saavutettavuus ja saatavuus. Valitse projektillesi olennaiset vaatimukset ja sovi niiden tärkeys tilaajan kanssa. Yllä olevat tavoitteet ovat opetusesimerkin valintoja, eivät kaikkien järjestelmien yleisiä raja-arvoja.

Järjestelmän toiminnan kuvaus

Sovellukseen toteutetaan seuraavat toiminnot:

  • Voidakseen katsoa henkilötietonsa opiskelijan on kirjauduttava sovellukseen.
  • Voidakseen katsoa arvosanansa opiskelijan on kirjauduttava sovellukseen.
  • Voidakseen ilmoittautua kurssille opiskelijan on kirjauduttava sovellukseen.
  • Jos kirjautuminen onnistuu, opiskelijalle avautuu valikko, josta hän voi valita henkilötietojen katselun, arvosanojen katselun tai kurssille ilmoittautumisen.
  • Mikäli kirjautuminen ei onnistu, palataan kirjautumisruudulle.

Käyttöönottokaavio

Tämä yleistasoinen kaavio näyttää, että opiskelija käyttää oppilasrekisteriä omalla laitteellaan verkkoyhteyden kautta. Se ei vielä määrittele sovelluksen toteutusteknologioita eikä palveluympäristön sisäistä rakennetta. Kaavio on havainnollistettu Mermaidin vuokaaviosyntaksilla.

flowchart LR
    subgraph StudentDevice["Opiskelijan laite"]
        UserInterface["Oppilasrekisterin käyttöliittymä"]
    end

    subgraph ServiceEnvironment["Palveluympäristö"]
        RegistryService["Oppilasrekisteri"]
    end

    UserInterface <-->|"Verkkoyhteys"| RegistryService
Näytä Mermaid-koodiPiilota Mermaid-koodi
flowchart LR
    subgraph StudentDevice["Opiskelijan laite"]
        UserInterface["Oppilasrekisterin käyttöliittymä"]
    end

    subgraph ServiceEnvironment["Palveluympäristö"]
        RegistryService["Oppilasrekisteri"]
    end

    UserInterface <-->|"Verkkoyhteys"| RegistryService

Käyttötapauskaavio

Käyttötapauskaavio kokoaa käyttäjän tavoitteet ja järjestelmän tarjoamat toiminnot. Aloita tunnistamalla käyttäjäroolit ja se, mitä kukin haluaa saada aikaan. Tarkemmat etenemisvaiheet ja poikkeukset kuvataan käyttötapauskorteissa.

usecase-beta
    direction LR
    actor Student("Student")
    systemBoundary Application["Student registry"]
        Login("Log in")
        ViewInfo("View personal information")
        ViewGrades("View grades")
        RegisterCourse("Register for course")
    end

    Student --> Login
    Student --> ViewInfo
    Student --> ViewGrades
    Student --> RegisterCourse
    ViewInfo ..> : include Login
    ViewGrades ..> : include Login
    RegisterCourse ..> : include Login
Näytä Mermaid-koodiPiilota Mermaid-koodi
usecase-beta
    direction LR
    actor Student("Student")
    systemBoundary Application["Student registry"]
        Login("Log in")
        ViewInfo("View personal information")
        ViewGrades("View grades")
        RegisterCourse("Register for course")
    end

    Student --> Login
    Student --> ViewInfo
    Student --> ViewGrades
    Student --> RegisterCourse
    ViewInfo ..> : include Login
    ViewGrades ..> : include Login
    RegisterCourse ..> : include Login

Viestiyhteyskaavio

Kaavio näyttää kirjautumisen ja sitä seuraavan toimintovalinnan opiskelijan näkökulmasta. Oppilasrekisteri esitetään yhtenä kokonaisuutena, joten kaavio ei vielä ota kantaa käyttöliittymän, rajapinnan tai tietojen tallennuksen toteutukseen.

sequenceDiagram
    actor Student as Opiskelija
    participant Registry as Oppilasrekisteri

    Student->>Registry: Kirjautuu
    alt Kirjautuminen onnistuu
        Registry-->>Student: Näyttää valikon
        alt Henkilötietojen katselu
            Student->>Registry: Valitsee henkilötiedot
            Registry-->>Student: Näyttää henkilötiedot
        else Arvosanojen katselu
            Student->>Registry: Valitsee arvosanat
            Registry-->>Student: Näyttää arvosanat
        else Kurssille ilmoittautuminen
            Student->>Registry: Valitsee kurssin ja ilmoittautuu
            Registry-->>Student: Näyttää vahvistuksen
        end
    else Kirjautuminen epäonnistuu
        Registry-->>Student: Näyttää kirjautumisen uudelleen
    end
Näytä Mermaid-koodiPiilota Mermaid-koodi
sequenceDiagram
    actor Student as Opiskelija
    participant Registry as Oppilasrekisteri

    Student->>Registry: Kirjautuu
    alt Kirjautuminen onnistuu
        Registry-->>Student: Näyttää valikon
        alt Henkilötietojen katselu
            Student->>Registry: Valitsee henkilötiedot
            Registry-->>Student: Näyttää henkilötiedot
        else Arvosanojen katselu
            Student->>Registry: Valitsee arvosanat
            Registry-->>Student: Näyttää arvosanat
        else Kurssille ilmoittautuminen
            Student->>Registry: Valitsee kurssin ja ilmoittautuu
            Registry-->>Student: Näyttää vahvistuksen
        end
    else Kirjautuminen epäonnistuu
        Registry-->>Student: Näyttää kirjautumisen uudelleen
    end

Käyttötapauskortit

Kustakin olennaisesta käyttötapauksesta laaditaan yleensä oma käyttötapauskortti, jossa kuvataan toiminnon tavoite, eteneminen ja poikkeukset tarkemmin kuin käyttötapauskaaviossa. Tässä esitetään malliksi vain yksi kortti, joka vastaa kaavion "Register for course" -käyttötapausta.

TUNNISTE KT-0001 VERSIO 1.0
NIMI Ilmoittaudu kurssille
SUORITTAJAT Opiskelija, oppilasrekisteri
TAVOITE Opiskelija ilmoittautuu valitsemalleen kurssille.
ESIEHDOT Opiskelija on kirjautunut sovellukseen ja järjestelmässä on ilmoittautumiseen tarjolla oleva kurssi.
KUVAUS 1. Opiskelija valitsee valikosta kurssille ilmoittautumisen.
2. Järjestelmä näyttää ilmoittautumiseen tarjolla olevat kurssit.
3. Opiskelija valitsee kurssin ja painaa Ilmoittaudu-painiketta.
4. Järjestelmä tallentaa opiskelijan ilmoittautumisen. (P1)
5. Järjestelmä näyttää vahvistuksen ilmoittautumisesta.
LOPPUEHDOT Ilmoittautuminen on tallennettu ja opiskelija on saanut vahvistuksen.
POIKKEUKSET P1: Tallennus epäonnistuu – järjestelmä ilmoittaa virheestä eikä näytä onnistumisvahvistusta.
AVOIMET ASIAT Voiko opiskelija perua ilmoittautumisensa myöhemmin?

Käyttöliittymän hahmotelma

Käyttötapausten pohjalta voidaan luonnostella sovelluksen näkymät. Onnistunut kirjautuminen avaa StudentInfo-valikon, josta opiskelija siirtyy haluamaansa toimintoon. Epäonnistuneen kirjautumisen jälkeen pysytään Login-näkymässä.

Mermaid ei sovellu varsinaisten käyttöliittymänäkymien luonnosteluun, vaikka sillä voi kuvata näkymien välisen kulun. Luonnokset voi piirtää esimerkiksi Excalidrawilla osoitteessa https://excalidraw.com/ ja ladata PNG- tai SVG-kuvatiedostoina. Alla olevat esimerkkinäkymät on hahmoteltu HTML:llä ja CSS:llä.

Näkymät ovat karkeita luonnoksia. Kentät ja painikkeet näyttävät suunnitellun sisällön ja kulun.

Login

Kirjaudu sisään
Opiskelijatunnus
opiskelija123
Salasana
••••••••
Kirjaudu

Virheellinen kirjautuminen palauttaa tähän näkymään.

StudentInfo

Opiskelijan valikko

Valitse, mitä haluat tehdä:

Omat tiedot → MyData
Kurssisuoritukset → MyGrades
Ilmoittaudu kurssille → EnrollToCourse
Kirjaudu ulos

MyData

Omat henkilötiedot
NimiEsimerkki Opiskelija
Opiskelijatunnusopiskelija123
Sähköpostiesimerkki@oppilaitos.fi
← Takaisin valikkoon

MyGrades

Kurssisuoritukset
KurssiArvosana
Ohjelmoinnin perusteet4
Tietokannat5
← Takaisin valikkoon

EnrollToCourse

Ilmoittaudu kurssille
OhjelmistotuotantoIlmoittaudu
VerkkopalvelutIlmoittaudu

Onnistunut ilmoittautuminen vahvistetaan tässä näkymässä.

← Takaisin valikkoon

Vaatimusmäärittelyn tarkistuslista

  • Ymmärtääkö tilaaja järjestelmän tavoitteen, käyttäjät ja rajauksen?
  • Onko tärkeimmille toiminnoille kuvattu onnistuminen, poikkeukset ja käyttöoikeudet?
  • Ovatko laatuvaatimukset ja hyväksymiskriteerit todennettavissa?
  • Kuvaavatko teksti, käyttötapauskortit ja kaaviot samaa toimintaa?
  • Onko avoimille asioille sovittu selvittäjä? Esimerkiksi ilmoittautumisen peruminen on vielä ratkaistava ennen sen toteuttamista.
Suunnitteluvaihe (Tekninen määrittely)

Tekninen määrittely kuvaa, miten toiminnallisessa määrittelyssä kuvatut toiminnot toteutetaan. Tässä esimerkissä valitaan sovelluksen osat, niiden välinen viestintä, luokkarakenne ja tietokannan rakenne.

Vaatimuksesta tekniseksi ratkaisuksi

Pidä vaatimusten tunnisteet mukana suunnittelussa. Näin toteutusratkaisulle löytyy peruste ja jokaiselle vaatimukselle voidaan suunnitella testi. Esimerkiksi vaatimus V-01 tarkentuu seuraavasti:

  • Vastuu: REST-rajapinta tarkistaa opiskelijan henkilöllisyyden ja oikeuden tietoihin jokaisella arvosanahaulla.
  • Rajapinta: GET /api/me/grades palauttaa kirjautuneen opiskelijan suoritukset. Opiskelijan tunniste johdetaan palvelimella varmennetusta tunnisteesta, eikä asiakkaan lähettämää opiskelijatunnusta käytetä käyttöoikeuden perusteena.
  • Tietojen haku: GradeModel rajaa parametrisoidun tietokantahaun tunnistetun opiskelijan tietoihin.
  • Virhetilanne: puuttuva tai virheellinen kirjautumistunniste tuottaa HTTP 401 -vastauksen. Käyttöliittymä pyytää kirjautumaan uudelleen.
  • Todentaminen: testissä käytetään kahta opiskelijaa ja varmistetaan, ettei toinen saa toisen arvosanoja myöskään muokkaamalla pyyntöä.

Tämä tarkentaa jäljempänä esitettyjä yleistasoisia kaavioita. Kuvaa omassa teknisessä määrittelyssäsi myös rajapintojen pyyntöjen ja vastausten tietosisältö sekä muut olennaiset virhevastaukset. Pelkkä nuoli osien välillä ei vielä määrittele niiden välistä sopimusta.

Ratkaisujen valinta ja perustelut

Kirjaa keskeisistä ratkaisuista, mitä valittiin ja miksi. Tässä Qt-asiakas ja Node.js-rajapinta ovat opetusesimerkin teknologiavalintoja. Rajapinta keskittää käyttöoikeuksien tarkistamisen palvelimelle, ja relaatiotietokanta sopii opiskelijoiden, kurssien ja ilmoittautumisten välisten suhteiden tallentamiseen. Omassa projektissa perusteluja voivat olla myös kohdeympäristö, ylläpidettävyys ja tiimin osaaminen.

Sovi lisäksi tietojen validointi, virheiden käsittely ja tallennuksen eheys. Jos samalle kurssille saa ilmoittautua vain kerran, sääntö pitää ensin hyväksyä vaatimukseksi ja sen jälkeen toteuttaa esimerkiksi opiskelijan ja kurssin yhdistelmän yksikäsitteisyysrajoitteella. Tekninen ratkaisu ei saa huomaamatta päättää käyttäjää koskevaa toimintasääntöä.

Käyttöönottokaavio

Käyttöönottokaavio näyttää, missä laitteissa sovelluksen osat toimivat ja miten ne ovat yhteydessä toisiinsa. Asiakassovellus toteutetaan C++:lla ja Qt:lla, REST-rajapinta Node.js:llä ja Expressillä. Tiedot tallennetaan MySQL-tietokantaan. Kaavio on havainnollistettu Mermaidin vuokaaviosyntaksilla.

flowchart LR
    subgraph ClientMachine["Client device"]
        QtApp["Qt application (C++)"]
    end

    subgraph Server["Server"]
        RestAPI["REST API (Node.js / Express)"]
        Database[("StudentDb (MySQL)")]
    end

    QtApp <-->|"HTTPS / JSON"| RestAPI
    RestAPI <-->|"MySQL protocol"| Database
Näytä Mermaid-koodiPiilota Mermaid-koodi
flowchart LR
    subgraph ClientMachine["Client device"]
        QtApp["Qt application (C++)"]
    end

    subgraph Server["Server"]
        RestAPI["REST API (Node.js / Express)"]
        Database[("StudentDb (MySQL)")]
    end

    QtApp <-->|"HTTPS / JSON"| RestAPI
    RestAPI <-->|"MySQL protocol"| Database

Komponenttikaavio (yksinkertaistettu)

Qt-sovellus ja REST-rajapinta voidaan tässä tulkita ohjelmiston pääkomponenteiksi. MySQL-laatikko kuvaa niiden käyttämää tietokantaa, joka ei itsessään ole ohjelmistokomponentti. Sisäiset laatikot kuvaavat esimerkiksi näkymiä ja moduuleja. Mermaidin vuokaaviosyntaksilla tehty kuva havainnollistaa osien riippuvuuksia, mutta ei noudata UML-komponenttikaavion merkintöjä täsmällisesti.

Toteutuksessa on valittu MVC-mallia mukaileva työnjako: Qt-sovellus toteuttaa näkymät (View), Express.js-rajapinnan reittien käsittelijät hoitavat ohjaimen tehtävät (Controller) ja StudentModel-, GradeModel- ja CourseModel-moduulit vastaavat tietojen käsittelystä (Model). Näkymät sijaitsevat erillisessä Qt-asiakassovelluksessa.

flowchart TD
    subgraph frontend["Qt frontend"]
        MainWindow["MainWindow"]
        Login_Qt["Login"]
        StudentInfo_Qt["StudentInfo"]
        MyData_Qt["MyData"]
        MyGrades_Qt["MyGrades"]
        EnrollToCourse_Qt["EnrollToCourse"]
        MainWindow --> Login_Qt
        Login_Qt --> StudentInfo_Qt
        StudentInfo_Qt --> MyData_Qt
        StudentInfo_Qt --> MyGrades_Qt
        StudentInfo_Qt --> EnrollToCourse_Qt
    end

    subgraph backend["REST API backend"]
        RouteLogin["RouteLogin"]
        RouteStudent["RouteStudent"]
        RouteGrade["RouteGrade"]
        RouteCourse["RouteCourse"]
        Student_model["StudentModel"]
        Grade_model["GradeModel"]
        Course_model["CourseModel"]
        DatabaseJs["database.js"]
        RouteLogin --> Student_model
        RouteStudent --> Student_model
        RouteGrade --> Grade_model
        RouteCourse --> Course_model
        Student_model --> DatabaseJs
        Grade_model --> DatabaseJs
        Course_model --> DatabaseJs
    end

    subgraph mysql["MySQL database"]
        studentdb[("studentdb")]
    end

    Login_Qt -->|"HTTPS"| RouteLogin
    MyData_Qt -->|"HTTPS"| RouteStudent
    MyGrades_Qt -->|"HTTPS"| RouteGrade
    EnrollToCourse_Qt -->|"HTTPS"| RouteCourse
    DatabaseJs --> studentdb
Näytä Mermaid-koodiPiilota Mermaid-koodi
flowchart TD
    subgraph frontend["Qt frontend"]
        MainWindow["MainWindow"]
        Login_Qt["Login"]
        StudentInfo_Qt["StudentInfo"]
        MyData_Qt["MyData"]
        MyGrades_Qt["MyGrades"]
        EnrollToCourse_Qt["EnrollToCourse"]
        MainWindow --> Login_Qt
        Login_Qt --> StudentInfo_Qt
        StudentInfo_Qt --> MyData_Qt
        StudentInfo_Qt --> MyGrades_Qt
        StudentInfo_Qt --> EnrollToCourse_Qt
    end

    subgraph backend["REST API backend"]
        RouteLogin["RouteLogin"]
        RouteStudent["RouteStudent"]
        RouteGrade["RouteGrade"]
        RouteCourse["RouteCourse"]
        Student_model["StudentModel"]
        Grade_model["GradeModel"]
        Course_model["CourseModel"]
        DatabaseJs["database.js"]
        RouteLogin --> Student_model
        RouteStudent --> Student_model
        RouteGrade --> Grade_model
        RouteCourse --> Course_model
        Student_model --> DatabaseJs
        Grade_model --> DatabaseJs
        Course_model --> DatabaseJs
    end

    subgraph mysql["MySQL database"]
        studentdb[("studentdb")]
    end

    Login_Qt -->|"HTTPS"| RouteLogin
    MyData_Qt -->|"HTTPS"| RouteStudent
    MyGrades_Qt -->|"HTTPS"| RouteGrade
    EnrollToCourse_Qt -->|"HTTPS"| RouteCourse
    DatabaseJs --> studentdb

Määrittelyvaiheessa laadittuja kaavioita ja luonnoksia voidaan joutua tarkentamaan suunnitteluvaiheessa. Määrittelyvaiheen viestiyhteyskaavio kuvaa opiskelijan ja oppilasrekisterin vuorovaikutusta yleisellä tasolla. Seuraavassa kaaviossa sama tapahtumakulku tarkentuu käyttöliittymän, rajapinnan ja tietokannan välisiksi viesteiksi. Myös käyttötapauskaavio ja käyttötapauskortti toimivat teknisen suunnittelun lähtökohtina.

Viestiyhteyskaavio

Viestiyhteyskaavio näyttää kirjautumisen ja opiskelijan toimintovalinnan etenemisen käyttöliittymän, REST-rajapinnan ja tietokannan välillä. Näin määrittelyvaiheen yleistasoinen kuvaus tarkentuu tekniseksi viestinnäksi.

sequenceDiagram
    actor Student
    participant UI as User Interface
    participant API as REST API
    participant DB as Database

    Student->>UI: Enter credentials
    UI->>API: Submit login request
    API->>DB: Verify credentials
    DB-->>API: Verification result
    alt Login successful
        API-->>UI: Session token
        UI-->>Student: Display menu
        alt View personal information
            Student->>UI: Select personal information
            UI->>API: Request personal information
            API->>DB: Fetch personal information
            DB-->>API: Personal information
            API-->>UI: Personal information
            UI-->>Student: Show personal information
        else View grades
            Student->>UI: Select grades
            UI->>API: Request grades
            API->>DB: Fetch grades
            DB-->>API: Grades
            API-->>UI: Grades
            UI-->>Student: Show grades
        else Register for course
            Student->>UI: Select course registration
            UI->>API: Request registration
            API->>DB: Register student for course
            DB-->>API: Confirmation
            API-->>UI: Confirmation
            UI-->>Student: Show confirmation
        end
    else Login unsuccessful
        API-->>UI: Authentication failed
        UI-->>Student: Show login form again
    end
Näytä Mermaid-koodiPiilota Mermaid-koodi
sequenceDiagram
    actor Student
    participant UI as User Interface
    participant API as REST API
    participant DB as Database

    Student->>UI: Enter credentials
    UI->>API: Submit login request
    API->>DB: Verify credentials
    DB-->>API: Verification result
    alt Login successful
        API-->>UI: Session token
        UI-->>Student: Display menu
        alt View personal information
            Student->>UI: Select personal information
            UI->>API: Request personal information
            API->>DB: Fetch personal information
            DB-->>API: Personal information
            API-->>UI: Personal information
            UI-->>Student: Show personal information
        else View grades
            Student->>UI: Select grades
            UI->>API: Request grades
            API->>DB: Fetch grades
            DB-->>API: Grades
            API-->>UI: Grades
            UI-->>Student: Show grades
        else Register for course
            Student->>UI: Select course registration
            UI->>API: Request registration
            API->>DB: Register student for course
            DB-->>API: Confirmation
            API-->>UI: Confirmation
            UI-->>Student: Show confirmation
        end
    else Login unsuccessful
        API-->>UI: Authentication failed
        UI-->>Student: Show login form again
    end

Luokkakaavio

Seuraavat kaaviot kuvaavat valittuja toteutuksen osia, niiden tietoja, toimintoja ja välisiä suhteita. Ne eivät esitä sovelluksen koko rakennetta.

REST API:n luokkakaavio

Edellä kuvattu MVC-mallia mukaileva työnjako näkyy reitti- ja Model-moduulien välisinä riippuvuuksina. Express-rajapinnan voi toteuttaa myös luokilla, mutta reitit ja väliohjelmistot rakennetaan usein funktioista ja moduuleista. Siksi tämä luokkakaavion merkintöjä käyttävä kuva havainnollistaa osien vastuita ja riippuvuuksia eikä vastaa yksi yhteen koodin luokkia. Esimerkiksi database.js on moduuli, joka vie connection-yhteysaltaan StudentModelin ja GradeModelin käyttöön. Qt-sovelluksen lomakkeet puolestaan on tässä mallinnettu C++-luokkina, joten niiden luokkakaavio vastaa suoremmin toteutuksen rakennetta.

classDiagram
    class App {
        -router: Router
        +authenticateToken(request, response, next) void
        +use(root) void
        +use(login) void
        +use(student) void
        +use(grade) void
    }

    class RouteLogin {
        -router: Router
        -bcrypt: bcryptjs
        -jwt: jsonwebtoken
        -config: dotenv
        -generateAccessToken(username) string
        +POST() void
    }

    class RouteStudent {
        -router: Router
        +GET() jsonArray
        +GET(username) jsonObject
        +POST(jsonArray) int
        +PUT(string, jsonArray) int
        +DELETE(string) int
    }

    class RouteGrade {
        -router: Router
        +GET(username) jsonArray
    }

    class StudentModel {
        -connection: Pool
        -query(string) void
        +getAll(callback) QueryResult
        +getOne(string, callback) QueryResult
        +add(jsonArray, callback) QueryResult
        +update(string, jsonArray, callback) QueryResult
        +delete(string, callback) QueryResult
    }

    class GradeModel {
        -connection: Pool
        +getByStudent(username, callback) QueryResult
    }

    class DatabaseJs["database.js (module)"] {
        +connection: Pool
    }

    App --> RouteLogin
    App --> RouteStudent
    App --> RouteGrade
    RouteStudent --> StudentModel
    RouteLogin --> StudentModel
    RouteGrade --> GradeModel
    StudentModel ..> DatabaseJs
    GradeModel ..> DatabaseJs
Näytä Mermaid-koodiPiilota Mermaid-koodi
classDiagram
    class App {
        -router: Router
        +authenticateToken(request, response, next) void
        +use(root) void
        +use(login) void
        +use(student) void
        +use(grade) void
    }

    class RouteLogin {
        -router: Router
        -bcrypt: bcryptjs
        -jwt: jsonwebtoken
        -config: dotenv
        -generateAccessToken(username) string
        +POST() void
    }

    class RouteStudent {
        -router: Router
        +GET() jsonArray
        +GET(username) jsonObject
        +POST(jsonArray) int
        +PUT(string, jsonArray) int
        +DELETE(string) int
    }

    class RouteGrade {
        -router: Router
        +GET(username) jsonArray
    }

    class StudentModel {
        -connection: Pool
        -query(string) void
        +getAll(callback) QueryResult
        +getOne(string, callback) QueryResult
        +add(jsonArray, callback) QueryResult
        +update(string, jsonArray, callback) QueryResult
        +delete(string, callback) QueryResult
    }

    class GradeModel {
        -connection: Pool
        +getByStudent(username, callback) QueryResult
    }

    class DatabaseJs["database.js (module)"] {
        +connection: Pool
    }

    App --> RouteLogin
    App --> RouteStudent
    App --> RouteGrade
    RouteStudent --> StudentModel
    RouteLogin --> StudentModel
    RouteGrade --> GradeModel
    StudentModel ..> DatabaseJs
    GradeModel ..> DatabaseJs

Qt sovelluksen luokkakaavio

Onnistuneen kirjautumisen jälkeen avautuu StudentInfo-lomake. Siitä opiskelija voi siirtyä MyData-lomakkeeseen katsomaan henkilötietoja, MyGrades-lomakkeeseen katsomaan kurssisuorituksia tai EnrollToCourse-lomakkeeseen ilmoittautumaan kurssille.

classDiagram
    class MainWindow {
        -objLogin: Login
        -on_btnStart_clicked() void
    }

    class Login {
        -postManager: QNetworkAccessManager
        -reply: QNetworkReply
        -response_data: QByteArray
        -objStudentInfo: StudentInfo
        -on_btnLogin_clicked() void
        -loginSlot(reply) void
    }

    class StudentInfo {
        -username: QString
        -myToken: QByteArray
        -objMyData: MyData
        -objMyGrades: MyGrades
        -objEnrollToCourse: EnrollToCourse
        -on_btnData_clicked() void
        -on_btnGrade_clicked() void
        -on_btnEnroll_clicked() void
        +setUsername(newUsername) void
        +setMyToken(newMyToken) void
    }

    class MyData {
        -username: QString
        -myToken: QByteArray
        -dataManager: QNetworkAccessManager
        -reply: QNetworkReply
        -response_data: QByteArray
        +loadPersonalData() void
        -dataSlot(reply) void
    }

    class MyGrades {
        -username: QString
        -myToken: QByteArray
        -gradeManager: QNetworkAccessManager
        -reply: QNetworkReply
        -response_data: QByteArray
        +loadGrades() void
        -gradeSlot(reply) void
    }

    class EnrollToCourse {
        -username: QString
        -myToken: QByteArray
        -enrollmentManager: QNetworkAccessManager
        -reply: QNetworkReply
        -response_data: QByteArray
        +enroll(courseId) void
        -enrollmentSlot(reply) void
    }

    MainWindow *-- Login
    Login *-- StudentInfo
    StudentInfo *-- MyData
    StudentInfo *-- MyGrades
    StudentInfo *-- EnrollToCourse
Näytä Mermaid-koodiPiilota Mermaid-koodi
classDiagram
    class MainWindow {
        -objLogin: Login
        -on_btnStart_clicked() void
    }

    class Login {
        -postManager: QNetworkAccessManager
        -reply: QNetworkReply
        -response_data: QByteArray
        -objStudentInfo: StudentInfo
        -on_btnLogin_clicked() void
        -loginSlot(reply) void
    }

    class StudentInfo {
        -username: QString
        -myToken: QByteArray
        -objMyData: MyData
        -objMyGrades: MyGrades
        -objEnrollToCourse: EnrollToCourse
        -on_btnData_clicked() void
        -on_btnGrade_clicked() void
        -on_btnEnroll_clicked() void
        +setUsername(newUsername) void
        +setMyToken(newMyToken) void
    }

    class MyData {
        -username: QString
        -myToken: QByteArray
        -dataManager: QNetworkAccessManager
        -reply: QNetworkReply
        -response_data: QByteArray
        +loadPersonalData() void
        -dataSlot(reply) void
    }

    class MyGrades {
        -username: QString
        -myToken: QByteArray
        -gradeManager: QNetworkAccessManager
        -reply: QNetworkReply
        -response_data: QByteArray
        +loadGrades() void
        -gradeSlot(reply) void
    }

    class EnrollToCourse {
        -username: QString
        -myToken: QByteArray
        -enrollmentManager: QNetworkAccessManager
        -reply: QNetworkReply
        -response_data: QByteArray
        +enroll(courseId) void
        -enrollmentSlot(reply) void
    }

    MainWindow *-- Login
    Login *-- StudentInfo
    StudentInfo *-- MyData
    StudentInfo *-- MyGrades
    StudentInfo *-- EnrollToCourse

Tietokannan suunnittelu

Edellisistä käyttötapauksista, käyttöliittymäluonnoksista ja kaavioista voidaan etsiä tietoja, joita sovelluksen täytyy tallentaa. Tässä esimerkissä niitä ovat:

  • Opiskelija: opiskelijatunnus, nimi, sähköposti ja kirjautumista varten salasanan tiiviste.
  • Kurssi: kurssitunnus, nimi ja opintopisteet.
  • Ilmoittautuminen: tieto siitä, kuka opiskelija on ilmoittautunut mille kurssille sekä ilmoittautumisen ajankohta ja tila.
  • Suoritus: ilmoittautumiseen liittyvä arvosana ja suorituspäivä.

Tietotarpeista voidaan laatia esimerkiksi seuraava yksinkertaistettu ER-malli. Se näyttää myös tietojen väliset suhteet: opiskelija voi ilmoittautua usealle kurssille, ja ilmoittautumisesta voi syntyä yksi suoritus. Taulujen tunnisteet ja muut tarkemmat kentät ovat tietokantasuunnittelussa tehtäviä valintoja.

Mermaidin ER-syntaksi vaatii suhteen selitekentän. Koodissa käytetään tyhjää selitettä, jotta kaaviossa näkyvät vain yhteydet ja niiden lukumääräsuhteet. Kaaviokohtainen asetteluasetus jättää taulujen väliin enemmän tilaa, jotta suhteen merkit erottuvat.

---
config:
  layout: dagre
  er:
    rankSpacing: 140
---
erDiagram
    STUDENT {
        int student_id PK
        string student_number UK
        string name
        string email
        string password_hash
    }

    COURSE {
        int course_id PK
        string name
        int credits
    }

    ENROLLMENT {
        int enrollment_id PK
        int student_id FK
        int course_id FK
        date enrollment_date
        string status
    }

    COURSE_COMPLETION {
        int completion_id PK
        int enrollment_id FK, UK
        int grade
        date completion_date
    }

    STUDENT ||--o{ ENROLLMENT : ""
    COURSE ||--o{ ENROLLMENT : ""
    ENROLLMENT ||--o| COURSE_COMPLETION : ""
Näytä Mermaid-koodiPiilota Mermaid-koodi
---
config:
  layout: dagre
  er:
    rankSpacing: 140
---
erDiagram
    STUDENT {
        int student_id PK
        string student_number UK
        string name
        string email
        string password_hash
    }

    COURSE {
        int course_id PK
        string name
        int credits
    }

    ENROLLMENT {
        int enrollment_id PK
        int student_id FK
        int course_id FK
        date enrollment_date
        string status
    }

    COURSE_COMPLETION {
        int completion_id PK
        int enrollment_id FK, UK
        int grade
        date completion_date
    }

    STUDENT ||--o{ ENROLLMENT : ""
    COURSE ||--o{ ENROLLMENT : ""
    ENROLLMENT ||--o| COURSE_COMPLETION : ""

Teknisen määrittelyn tarkistuslista

  • Onko jokaisella olennaisella vaatimuksella toteutusratkaisu ja tapa testata se?
  • Ovatko osien vastuut, rajapintojen tietosisällöt ja virhetilanteet riittävän selviä toteuttajalle?
  • Vastaavatko tietokannan suhteet ja rajoitteet sovittuja toimintasääntöjä?
  • Onko tunnistautuminen ja käyttöoikeuksien tarkistus kuvattu palvelimen näkökulmasta?
  • Onko kuvattu, miten sovellus otetaan käyttöön ja miten asetukset, salaisuudet ja varmuuskopiointi hoidetaan?

Määrittelyjä tarkennetaan työn edetessä. Jos suunnittelussa havaitaan puuttuva sääntö tai ristiriita, päivitä ensin sovittu vaatimus ja sen jälkeen siihen liittyvät kuvaukset. Tämä sivu näyttää valittuja esimerkkejä; kokonaisen projektin dokumentaatiossa avoimet päätökset ja puuttuvat kuvaukset on täydennettävä.



Toggle Menu