Viikko 5
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
gitkvoit 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!