Allaolevien tehtävien deadline on maanantai 1.12. klo 23:59

Apua tehtävien tekoon kurssin Discord-kanavalla sekä kampuksella pajassa BK107:

  • ma 14.30-16.30
  • ti 12-16
  • to 12-16
  • pe 12-14

Liittyminen kurssin Discord-kanavalle tapahtuu komennolla /join course TKT20006 - Ohjelmistotuotanto - ohtu

Muista myös tämän viikon monivalintatehtävät, joiden deadline on sunnuntai 7.12. klo 23:59:00 .

Tehtävissä 1-3 jatketaan Gitin harjoittelua. Nämä tehtävät eivät näy palautuksissa mitenkään.

Tehtävä 4 liittyy materiaalin ohjelmistosuunnittelua käsittelevän osan 4 niihin lukuihin, joihin on merkitty [viikko 5]. Tehtävissä 5 ja 6 pääsemme hyödyntämään tekoälyä koodin katselmoinnissa sekä koodin tuottamisessa.

Typoja tai epäselvyyksiä tehtävissä?

Tee korjausehdotus editoimalla tätä tiedostoa GitHubissa.

Kurssipalaute

Kurssilla on käytössä normaalin lopussa kerättävän palautteen lisäksi ns. jatkuva palaute: voit antaa milloin vain kurssihenkilökunnalle anonyymiä palautetta osoitteessa https://norppa.helsinki.fi/targets/95023982/feedback

Ongelmia Poetryn kanssa?

Muutamia ohjeita täällä

Tehtävien palauttaminen

Tehtävät palautetaan GitHubiin, sekä merkitsemällä tehdyt tehtävät palautussovellukseen https://study.cs.helsinki.fi/stats/courses/ohtu2025 välilehdelle “my submission”.

Tämän viikon tehtävät 4-6 palautetaan jo edellisillä viikoilla käyttämääsi palautusrepositorioon, sinne tehtävän hakemiston viikko5 sisälle. Tehtäviä 1-3 ei palauteta.

Katso tarkempi ohje palautusrepositoriota koskien täältä.

1. Git: vahingossa tuhotun tiedoston palautus [versionhallinta]

Viikon 4 tehtävässä 5 palasimme jo menneisyyteen checkouttaamalla tagillä merkittyyn kohtaan. Katsotaan nyt miten voimme palauttaa jonkun menneisyydessä olevan tilanteen uudelleen voimaan.

Voit tehdä tämän ja kaksi seuraavaa tehtävää mihin tahansa repositorioon, tehtävät eivät näy palautuksissa.

Tee tiedosto nimeltään important.txt, lisää ja committaa se Gitiin

Poista tiedosto ja committaa

Tee jotain muutoksia johonkin tiedostoon ja committaa

Historiasi näyttää seuraavalta

(1) - (2) - (3)

Nykyhetki eli HEAD on (3). Commitissa (1) tiedosto important.txt on olemassa ja (2):ssa important.txt:ää ei ole.

  • Huom: komennolla gitk voit tutkia historiaa

Haluamme palauttaa tiedoston important.txt.

Selvitä sen commitin id, jossa tiedosto vielä on olemassa, tämä onnistuu gitk:lla tai komennolla git log

Anna komento git checkout 3290b03cea08af987ee7ea57bb98a4886b97efe0 -- important.txt missä pitkä merkkijono on siis kyseisen commitin id

Varmista että tiedosto important.txt on ilmestynyt staging-alueelle komennolla git status

Tee commit

Kadonnut tiedosto important.txt on palannut, ja versionhallinnassa!

Huom: koko id:tä ei komennossa tarvitse antaa, riittää antaa alusta niin monta merkkiä, että niiden perusteella id voidaan päätellä yksikäsitteisesti repositoriosi historiassa:

  • “Generally, eight to ten characters are more than enough to be unique within a project. For example, as of October 2017, the Linux kernel (which is a fairly sizable project) has over 700,000 commits and almost six million objects, with no two objects whose SHA-1s are identical in the first 11 characters.” Ks. lisää täältä
  • Täsmälleen samalla tavalla onnistuu olemassa olevan tiedoston vanhan version palauttaminen.

2. Git: commitin muutosten kumoaminen [versionhallinta]

Jatketaan siitä mihin edellisessä tehtävässä jäimme. Huomaamme, että juuri tehty commit oli virhe.

Kumotaan se komennolla git revert HEAD --no-edit

Komennossa HEAD viittaa siihen committiin, jonka kohdalla nyt ollaan.

Varmista, että edellisen commitin tekemä muutos (eli tiedoston important.txt lisääminen) kumoutuu

Komennon git revert seurauksena syntyy uusi commit, jossa edellisessä tehdyt muutokset on kumottu

  • Ilman optiota no-edit pääset editoimaan kumoamiseen liittyvään commitiin tulevaa viestiä
  • Huom: sanomalla git checkout HEAD^ pääsemme takaisin kumottuun tilanteeseen, eli mitään ei ole lopullisesti kadotettu

Vastaavalla tavalla voidaan kumota, eli revertata mikä tahansa commit, eli: git revert kumottavancommitinid

3. Git: rebase [versionhallinta]

Olemme jo törmänneet parissa aiemmassa tehtävässä (viikko 1, tehtävä 11 ja ja viikko 2 tehtävä 13) Gitin käsitteeseen rebase. Otetaan nyt selvää tarkemmin mistä on kysymys.

Lue https://www.atlassian.com/git/tutorials/rewriting-history/git-rebase tai/ja http://git-scm.com/book/en/Git-Branching-Rebasing.

Aikaansaa seuraavankaltainen tilanne branchien main ja haara välille:

------- main
\
 \--- haara

“Rebeissaa” haara mainiin, eli aikaansaa seuraava tilanne:

------- main
       \
        \--- haara

Varmista komennolla gitk --all että tilanne on haluttu.

“Mergeä” haara vielä mainiin, jolloin tilanne on seuraava:

------- \     main
         \--- haara

Lopputuloksena pitäisi siis olla lineaarinen historia ja main sekä haara samassa.

Varmista jälleen komennolla gitk --all että kaikki on kunnossa.

Poista branch haara. Kysy tarvittaessa AI:lta tai Googlelta miten branchin poisto tapahtuu.

Mikä on rebase-komennon käyttötarkoitus? Atlassianin git-ohje perustelee asiaa näin

The primary reason for rebasing is to maintain a linear project history. For example, consider a situation where the main branch has progressed since you started working on a feature branch. You want to get the latest updates to the main branch in your feature branch, but you want to keep your branch’s history clean so it appears as if you’ve been working off the latest main branch. This gives the later benefit of a clean merge of your feature branch back into the main branch. Why do we want to maintain a “clean history”? The benefits of having a clean history become tangible when performing Git operations to investigate the introduction of a regression.

4. Tenniksen pisteenlaskun refaktorointi

Kurssirepositorion hakemistossa viikko5/tennis, löytyy ohjelma, joka on tarkoitettu tenniksen pisteenlaskentaan.

Kopioi projekti palautusrepositorioosi, hakemiston viikko5 sisälle

Tee commit ja pushaa koodi GitHubiin

Tee tehtävää varten oma haara nimeltään tennis_refactoring

Varmista vielä, että olet seuraavassa tilanteessa ennen kuin jatkat seuraaviin askeleisiin

$ git status
On branch tennis_refactoring
nothing to commit, working tree clean

Pisteenlaskennan rajapinta on yksinkertainen. Metodi get_score kertoo voimassa olevan tilanteen tenniksessä käytetyn pisteenlaskennan määrittelemän tavan mukaan. Sitä mukaa kun jompi kumpi pelaajista voittaa palloja, kutsutaan metodia won_point, jossa parametrina on pallon voittanut pelaaja.

Esim. käytettäessä pisteenlaskentaa seuraavasti:

game = TennisGame("player1", "player2")

print(game.get_score())

game.won_point("player1")
print(game.get_score())

game.won_point("player1")
print(game.get_score())

game.won_point("player2")
print(game.get_score())

game.won_point("player1")
print(game.get_score())

game.won_point("player1")
print(game.get_score())

tulostuu

Love-All
Fifteen-Love
Thirty-Love
Thirty-Fifteen
Forty-Fifteen
Win for player1

Tulostuksessa siis kerrotaan mikä on pelitilanne kunkin pallon jälkeen kun player1 voittaa ensimmäiset 2 palloa, player2 kolmannen pallon ja player1 loput 2 palloa.

Tenniksen pisteenlaskennasta voit lukea enemmän esim. Wikipediasta, mutta se ei ole välttämätöntä tämän tehtävän tekemisen kannalta.

Pisteenlaskentaohjelman koodi toimii ja sillä on erittäin kattavat testit. Koodi on kuitenkin sisäiseltä laadultaan kelvotonta.

Tehtävänä on refaktoroida koodi luettavuudeltaan mahdollisimman ymmärrettäväksi

  • Koodissa tulee välttää “taikanumeroita” ja huonosti nimettyjä muuttujia
  • Koodi kannattaa jakaa moniin pieniin metodeihin, jotka nimennällään paljastavat oman toimintalogiikkansa
  • Etene refaktoroinnissa todella pienin askelin
  • Suorita testejä mahdollisimman usein
  • Yritä pitää ohjelma koko ajan toimintakunnossa, eli älä hajota testejä
  • Testeihin ohjelmassa ei tarvitse eikä edes saa koskea

Jos haluat käyttää jotain muuta kieltä kuin Pythonia, löytyy koodista ja testeistä versioita useilla eri kielillä osoitteesta https://github.com/emilybache/Tennis-Refactoring-Kata.

Kun olet valmis, commitoi koodi ja pushaa haara tennis_refactoring GitHubiin

Lisää samankaltaisia refaktorointitehtäviä löytyy Emily Bachen GitHubista.

5. Pull request ja koodin katselmointi

Tämän tehtävän tekeminen edellyttää, että sinulla on GitHub Education -jäsenyys.

Tee nyt GitHubissa Pull request haarasta tennis_refactoring haaraan main

GitHub ehkä jo ehdottaa Pull requestin tekemistä

Varmista, että PR kohdistuu haarasta tennis_refactoring haaraan main.

Kirjoita PR:lle kuvaus. Voit ottaa esim. täältä tai täältä mallia kuvaukselle.

Pyydä GitHub Copilotia tekemään PR:llesi koodin katselmointi:

Odota katselmoinnin valmistumista… omassa tapauksessani taisi mennä noin 10 minuuttia

Käy katselmoinnin tulos läpi. Hyväksy ehdotetut muutokset halutessasi ja merkitse kommentit selvitetyiksi (resolve conversation)

Mergeä Pull request main-haaraan

Kirjoita raportti katselmoinnista palautusrepositorioon hakemistoon viikko5 talletettavaan tiedoston review.md

Kerro raportissa

  • Mitä huomioita Copilot teki koodistasi
  • Olivatko ehdotetut muutokset hyviä
  • Kuinka hyödylliseksi koit Copilotin tekemän katselmoinnin

Lisää aiheesta GitHubin dokumentaatiossa

6. Good vibe with warehouses

Palataan jälleen viikolta 1 tutun Ohtuvaraston pariin. Tehtävässä on tarkoitus saada tekoäly koodaamaan Ohtuvarastolle web-käyttöliittymä, esim. Flask-sovelluskehystä käyttäen

Tee repositorioosi issue, jossa kuvaat mahdollisimman tarkasti minkälaisen sovelluksesta haluat:

Sovelluksen pitäisi mahdollistaa useiden varastojen luominen, muokkaaminen ja sisällön lisääminen tai poistaminen. Myös mahdolliset käytettävät kirjastot kuten Flask kannattaa mainita kuvauksessa.

Copilot käyttää issuen kuvausta promptina, joten kuvauksen laatuun kannattaa panostaa.

Assignaa issue Copilotille:

Copilot avaa Pull requestin työskentelyään varten:

Mene Pull requestin näkymään (ks. välilehti Pull requests), ja sieltä edelleen nappia “View session” painamalla katsomaan Copilotin työskentelyä

Copilot aloittaa tutustumalla projektiin ja luo suunnitelman

Seuraa Copilotin edistymistä

Copilotilla voi mennä aika kauan koodaillessa. Nyt on hyvä hetki esim. keittää kahvit tai hakea jääkaapista energiajuomatölkki.

Odota kunnes Copilot on valmis

Kun Copilot on valmis (itselläni meni noin 15 min) näet sen luoman koodin Pull requestin sivulta. Ainakin omassa tapauksessani Copilot on lisännyt PR:n sivulle myös kuvakaappauksia sovelluksesta.

Pull request on tällä hetkellä draft-tilassa. Muuta sen tilaa painamalla nappia “Ready for review”

Hae pull requestin koodia omalla koneellasi

Tämä tapahtuu komennoilla git fetch ja git checkout:

$ git fetch
remote: Enumerating objects: 38, done.
remote: Counting objects: 100% (36/36), done.
remote: Compressing objects: 100% (20/20), done.
remote: Total 25 (delta 9), reused 18 (delta 5), pack-reused 0 (from 0)
Unpacking objects: 100% (25/25), 13.12 KiB | 206.00 KiB/s, done.
From github.com:mluukkai/ohtuvarasto25
 * [new branch]      copilot/add-warehouse-management-ui -> origin/copilot/add-warehouse-management-ui
   a359cc1..7211227  user_interface -> origin/user_interface
$ git checkout copilot/add-warehouse-management-ui
branch 'copilot/add-warehouse-management-ui' set up to track 'origin/copilot/add-warehouse-management-ui'.
Switched to a new branch 'copilot/add-warehouse-management-ui'

Varmista, että koodi toimii

Oma sovellukseni oli konfiguroitu siten, että osoitteen http://localhost:5000/ sijaan sovellukseen pääsee käsiksi osoitteesta http://127.0.0.1:5000/

Tee sovellukselle katselmointi GitHubissa

Pääset tekemään katselmoinnin Pull requestin sivun yläoikealla olevasta napista “Add your review”. Saatat joutua uudelleenlataamaan sivun, jotta nappi ilmestyy näkyviin

Vaadi katselmoinnissa jotain muutoksia sovellukseen:

Valitse siis lomakkeelta Request changes. Kommenteissa tulee mainita @copilot, jotta Copilot suostuu tekemään muutokset

Seuraa jälleen Copilotin edistymistä napilla “View session”

Varmista vielä omalla koneellasi, että koodi toimii muutosten jälkeen

Kun olet tyytyväinen mergeä Pull request main-haaraan

Kirjoita raportti katselmoinnista palautusrepositorioon hakemistoon viikko5 talletettavaan tiedoston vibe.md

Kerro raportissa

  • Päätyikö Copilot toimivaan ja hyvään ratkaisuun
  • Oliko koodi selkeää
  • Opitko jotain uutta Copilotin tekemää koodia lukiessasi

Tässä erittäin yksinkertaisessa tapauksessa vibekoodaus saattaa tuottaa hämmästyttävänkin hyvän lopputuloksen. Tilanne on kuitenkin aivan erilainen todellisen, isomman järjestelmän kanssa, pelkkä vibetys, eli haluttavan toiminnallisuuden kuvailu ei useimmiten riitä siihen että ulos saadaan toimiva ja robusti ratkaisu.

Tehtävien palautus

Pushaa kaikki tekemäsi tehtävät (paitsi ne, joissa mainitaan, että tehtävää ei palauteta mihinkään) GitHubiin palautusrepositorioosi ja merkkaa tekemäsi tehtävät palautussovellukseen https://study.cs.helsinki.fi/stats/courses/ohtu2025

Vapaaehtoinen bonus-tehtävä

Kurssirepositorion hakemistossa viikko5/int-joukko on alun perin Javalla tehty, mutta nyt Pythoniksi alkuperäiselle tyylille uskollisena käännetty aloittelevan ohjelmoijan ratkaisu syksyn 2011 Ohjelmoinnin jatkokurssin viikon 2 tehtävään 3.

Kopioi projekti palautusrepositorioosi, hakemiston viikko5 sisälle.

Kyseinen opiskelija on edennyt urallaan pitkälle, hän on työskennellyt mm. Googlella ja useassa korkean profiilin Piilaakson start upissa.

Koodi simuloi vanhanaikaista ohjelmointikieltä kuten C:tä missä ei ole Pythonin listan tapaista valmista tietorakennetta, vaan ainoastaan listoja, joiden koko on kiinteä, ja joka määritellään listan luomishetkellä. Koodissa listan luominen tapahtuu metodilla _luo_lista:

class IntJoukko:
    # tämä metodi on ainoa tapa luoda listoja
    def _luo_lista(self, koko):
        return [0] * koko

    def __init__(self, kapasiteetti=None, kasvatuskoko=None):
        # ...
        
        # luodaan lista, jolla haluttu kapasiteetti
        self.ljono = self._luo_lista(self.kapasiteetti)
        self.alkioiden_lkm = 0

Kun joukkoon lisätään riittävä määrä uusia lukuja, tulee eteen tilanne, että joukon sisäistä listaa on kasvatettava. Tämä tapahtuu luomalla uusi lista metodilla _luo_lista:

    def lisaa(self, n):
        # ...
                
        # ei enää tilaa, luodaan uusi lista lukujen säilyttämiseen
        self.ljono = self._luo_lista(self.alkioiden_lkm + self.kasvatuskoko)

Koodi jättää hieman toivomisen varaa sisäisen laatunsa suhteen. Refaktoroi luokan IntJoukko koodi mahdollisimman siistiksi ja helposti ylläpidettäväksi.:

Poista copypaste

Vähennä monimutkaisuutta

Anna muuttujille selkeät nimet

Tee metodeista pienempiä ja hyvän koheesion omaavia

Ratkaisusi tulee toimia siten, että edelleen joukon sisäisen listan koko on kiinteä, ja lista luodaan metodilla _luo_lista, eli jos lista täyttyy, luodaan uusi lista metodin avulla.

Koodissa on joukko yksikkötestejä, jotka helpottavat refaktorointia.

HUOM: Suorita refaktorointi mahdollisimman pienin askelin, pidä koodi koko ajan toimivana. Suorita testit jokaisen refaktorointiaskeleen jälkeen!