-
Notifications
You must be signed in to change notification settings - Fork 57
Laskari 2
- tehtävät 4 ja 5 tehdään paikalliseen repositorioon, eli ne eivät näy palautuksessa mitenkään
- tee palautusta varten yksityinen repositorio ja lisää sille collaboratoriksi käyttäjä mluukkai, voit käyttää myös viikon 1 repositoriotasi
- jos et ole vielä ehtinyt saada GitHubin academic-tunnusta, voit tehdä palautuksen normaalia repositoriota käyttäen
- palautusrepositorion nimi ilmoitetaan tehtävien lopussa olevalla palautuslomakkeella
- lue ensin tiistain luennolla nopeasti läpikäytyjen asioiden kertaus https://github.com/mluukkai/ohtu2015/blob/master/web/riippuvuuksien_injektointi.md
- hae koodiesimerkit repostitoriosta https://github.com/mluukkai/ohtu2015/ (hakemistosta viikko2/RiippuvuuksienInjektointi) ja kokeile että kaikki toimivat
- järkevintä lienee että kloonaat repositorion paikalliselle koneellesi
- vaikka viime viikolla sama repositorio forkattiin, ei forkattua repositorioa saa ihan helposti synkronoitua alkuperäiseen
-
repositorion https://github.com/mluukkai/ohtu2015/ hakemistossa viikko2/Ohtu-NHLStatistics1 on ohjelma, jonka avulla on mahdollista tutkia http://nhl.com-sivulla olevia pelaajien tilastotietoja
-
Ohjelma koostuu kolmesta luokasta.
-
Statistics
on palvelun tarjoava luokka, se tarjoaa metodit yhden pelaajan tietojen näyttämiseen, pistepörssin näyttämiseen ja yhden joukkueen pelaajien tietojen näyttämiseen -
Player
on luokka, jonka olioina Statistics käsittelee yksittäisen pelaajan tietoja -
PlayerReader
on luokka, jonka avulla ohjelma käy hakemassa pelaajien tiedot internetistä
-
-
Ohjelma on nyt ikävästi struktoroitu ja esim. yksikkötestaus on kovin hankalaa
itse tehtävä:
- Määrittele rajapinta
Reader
, jolla on samat julkiset metodit kuin PlayerReaderilla, eli ainoastaan metodiList getPlayers()
. Laita PlayerReader toteuttamaan rajapinta. - Muokkaa ohjelman rakennetta siten, että Statictics saa konstruktoriparametrina
Reader
-tyyppisen olion. - Muokkaa pääohjelma siten, että se injektoi Statistics-oliolle PlayerReaderin ja kokeile että ohjelma toimii edelleen:
Statistics stats = new Statistics( new PlayerReader("http://nhlstats-2013-14.herokuapp.com/players.txt") );
- tee yksikkötestit luokalle Statistics
- testien rivi- ja haarautumakattavuuden tulee (Statistics-luokan osalta) olla 100% (mitataan coberturalla, ks. viikko 1)
- testit eivät saa käyttää verkkoyhteyttä
- verkkoyhteyden tarpeen saat eliminoitua luomalla testiä varten rajapinnan Reader-toteuttavan "stubin", jonka sisälle kovakoodaat palautettavan pelaajalistan
- voit luoda stubin testin sisälle anonyyminä sisäluokkana seuraavasti:
public class StaticsticsTest {
Statistics stats;
Reader readerStub = new Reader() {
public List<Player> getPlayers() {
ArrayList<Player> players = new ArrayList<Player>();
players.add(new Player("Semenko", "EDM", 4, 12));
players.add(new Player("Lemieux", "PIT", 45, 54));
players.add(new Player("Kurri", "EDM", 37, 53));
players.add(new Player("Yzerman", "DET", 42, 56));
players.add(new Player("Gretzky", "EDM", 35, 89));
return players;
}
};
// ...
}
Kun injektoit readerStub-olion testissä Statistics-oliolle, palauttaa se aina saman pelaajalistan.
lue brancheja käsittelevät osuudet seuraavista: https://we.riseup.net/debian/git-development-howto ja http://www.ralfebert.de/tutorials/git/
- jos haluat lukea hieman perusteellisemman selityksen asiasta, lue http://git-scm.com/book:n luku kolme
- tee samalla kaikki tekstien esimerkit
Kannattaa huomioida myös erittäin hyvä brancheja käsittelevä visuaalinen materiaali osoitteessa http://pcottle.github.com/learnGitBranching/
Varsin selkeältä vaikuttaa myös https://www.atlassian.com/git/tutorial/git-branches
huom: kun liikut branchien välillä kannattaa pitää working tree ja staging -alue tyhjinä!
tee seuraavat paikalliseen git-repositorioosi (kyseessä ei siis tarvitse olla tehtävien palautusrepositorio)
- luo repositorio ja committaa masteriin tiedosto masteri1.txt
- luo branch eka, siirry branchiin, luo sinne tiedosto eka.txt ja committaa
- siirry takaisin master-branchiin, tiedoston eka.txt ei pitäisi nyt näkyä
- lisää ja committaa masteriin tiedosto masteri2.txt
- mene branchiin eka ja tarkasta, että masteriin lisätty tiedosto ei ole branchissa
- lisää branchiin tavaraa, esim. tiedosto eka2.txt ja committaa
- siirry takaisin master-branchiin
- tarkasta että eka-branchiin lisätyt muutokset eivät ole masterissa
- tarkastele komennolla
gitk --all
miltä repositorio ja branchit näyttävät (gitk toimii windowsilla ainakin Github for Windowsin Git Shellissä.) - mergeä branchin eka sisältö masteriin
- katso jälleen miltä näyttää gitk --all
- tuhoa branchi eka
tee paikalliseen git-repoon seuraavat
- lisää master-branchiin tiedosto tarkea.txt, kirjota sinne muutama rivi tekstiä ja committaa
- tee uusi branchi toka, editoi tiedoston tarkea.txt loppua ja committaa
- mene takaisin master-branchiin, editoi tiedoston tarkea.txt alkua ja committaa
- mergeä branchin toka sisältö masteriin
- katso tiedoston tarkea.txt-sisältöä, sen pitäisi sisältää nyt molemmissa brancheissa tehdyt muutokset
- huom: jo tässä vaiheessa saattaa syntyä konflikti jos olet vahingossa muuttanut merkkejä väärästä kohtaa tiedostoa! Toimi tällöin ao. ohjeen mukaan.
- lisää jotain tiedoston loppuun ja committaa
- siirry branchiin toka
- lisää jotain tiedoston tarkea.txt loppuun ja committaa
- mergeä branchin master sisältö branchiin toka
- nyt pitäisi aiheutua konflikti
- ratkaise konflikti:
- editoi tiedoston tarkea.txt sisältö haluamaksesi
- ja toimi em. artikkelien ohjeen mukaan eli lisää konfliktoinut tiedosto staging-alueelle ja committoi
aloita lukemalla ProGit kirjasta luku Remote Branches
branch githubiin:
- lisää tehtävien palauttamiseen käyttämäsi GitHub-reposition paikalliseen kopioon branchit haara1 ja haara2
- mene branchiin haara1, lisää sinne tiedosto haara1.txt ja committaa
- mene branchiin haara2, lisää sinne tiedosto haara2.txt ja committaa
- pushaa uudet branchit GitHubiin
- tarkastele GitHub-repositoria selaimella, varmista että branchit syntyvät ja niillä on haluttu sisältö
kloonaa GitHub-repositoriosta koneellesi toinen kopio
- kuten huomaat, eivät branchit tule kloonattuun kopioon
- tee paikalliseen kopioon branch joka "träkkää" GitHub:issa olevan projektisi branchia haara1 (ks. http://git-scm.com/book/en/Git-Branching-Remote-Branches kohta Tracking Branches)
- lisää "träkkäävään" branchiin joku tiedosto, committaa ja pushaa branchi GitHubiin
- tarkastele GitHub-repositoria selaimella, varmista että branchi päivittyy
mene GitHub-repon alkuperäiseen paikalliseen kopioon
- mene branchiin haara1 ja pullaa muutokset GitHub:in vastaavasta branchista
- huom: koska kyseessä ei ole "träkkäävä" branchi, joudut pullaamaan komennolla
git pull origin haara1
- huom: koska kyseessä ei ole "träkkäävä" branchi, joudut pullaamaan komennolla
- mene branchiin haara2, lisää sitten tiedosto, committaa ja pushaa branchi GitHubiin
- huom: koska kyseessä ei ole "träkkäävä" branchi, ei git push riitä vaan joudut määrittelemään branchin jonne push kohdistuu eli antamaan komennon
git push origin haara2
- huom: koska kyseessä ei ole "träkkäävä" branchi, ei git push riitä vaan joudut määrittelemään branchin jonne push kohdistuu eli antamaan komennon
mene jälleen toiseen kopioon
- suorita komento
git remote show origin
- komento kertoo 'origin':issa eli githubissa olevien branchien ja paikallisten branchien suhteen
- tee sinne GitHub:issa olevan projektisi branchia haara2 träkkäävä branch
- suorita jälleen
git remote show origin
, mitä muutoksia huomaat? - tee branchiin muutoksia ja pushaa ne githubiin
- huom: koska kyseessä träkkäävä branch, riittää git push
- tarkastele GitHub-repositoria selaimella, varmista että branchi päivittyy
suorita vielä komento git remote show origin
alkuperäisessä paikallisessa kopiossa
Branchien kanssa työskentely voi aluksi tuntua sekavalta varsinkin jos GitHub:issa on myös useita brancheja.
Ohjelmistotimi voi käyttää Gitiä hyvin monella eri tyylillä. Artikkeli https://www.atlassian.com/git/workflows esittelee muutamia erilaisia tapoja järjestellä tiimin gitin käyttöön liittyvä workflow. Yksi yleinen tapa branchien käyttöön ovat ns. featurebranchit:
The core idea behind the Feature Branch Workflow is that all feature development should take place in a dedicated branch instead of the master branch. This encapsulation makes it easy for multiple developers to work on a particular feature without disturbing the main codebase. It also means the master branch will never contain broken code, which is a huge advantage for continuous integration environments.
Jos kiinnostaa, lue lisää yo. dokumentista.
Demonstroidaan usein esiintyvää tilannetta, jossa epäajantasaisen repositorion pushaaminen githubissa olevaan etärepositorioon epäonnistuu.
- mene alkuperäiseen repositorion alkuperäisen kopion master haaraan, tee joku muutos, commitoi ja pushaa se githubiin
- mene toisen kopion master-haaraan ja tee sinne joku muutos
- commitoi ja pushaa muutos githubiin
- kaikki ei kuitenkaan mene hyvin, seurauksena on seuraavantyylinen virheilmoitus:
mbp-18:ohtu-viikko1-2015 mluukkai$ git push To git@github.com:mluukkai/ohtu-viikko1-2015.git ! [rejected] master -> master (fetch first) error: failed to push some refs to 'git@github.com:mluukkai/ohtu-viikko1-2015.git' hint: Updates were rejected because the remote contains work that you do hint: not have locally. This is usually caused by another repository pushing hint: to the same ref. You may want to first merge the remote changes (e.g., hint: 'git pull') before pushing again. hint: See the 'Note about fast-forwards' in 'git push --help' for details. mbp-18:ohtu-viikko1-2015 mluukkai$
Virheen syynä on se, että githubissa oleva master-haara oli edellä paikallisen repositorion master-haaraa. Ongelma korjaantuu tekemällä ensin git pull
, ratkaisemalla mahdolliset konfliktit ja pushaamalla sitten uudelleen.
- eli toimi näin ja varmista, että tekemäsi muutokset menevät githubiin
Repositorion https://github.com/mluukkai/ohtu2015/ hakemistossa viikko2/Verkkokauppa1 on yksinkertaisen verkkokaupan ohjelmakoodi
-
tutustu koodiin, piirrä luokkakaavio ohjelman rakenteesta
-
ohjelman luokista
Pankki
,Varasto
,Viitegeneraattori
jaKirjanpito
ovat sellaisia, että niistä on tarkoitus olla olemassa vain yksi olio. Tälläisiä ainutkertaisia olioita sanotaan singletoneiksi. Koodissa singletonit ovat toteutettu "klassisella tavalla"- Singleton on GoF-kirjan yksi alkuperäisistä suunnittelumalleista, lue lisää singletoneista esim. täältä
- Singleton ei ole erinäisistä syistä enää oikein muodissa, ja korvaamme sen seuraavassa tehtävässä
-
kuten huomaamme, on koodissa toivottoman paljon konkreettisia riippuvuuksia:
- Varasto --> Kirjanpito
- Pankki --> Kirjanpito
- Kauppa --> Pankki
- Kauppa --> Viitegeneraatori
- Kauppa --> Varasto
-
Pura luokan
Kauppa
konkreettiset riippuvuudet rajapintojen avulla- HUOM: NetBeansissa on automaattinen refaktorointiominaisuus, jonka avulla luokasta saa helposti generoitua rajapinnan, jolla on samat metodit kuin luokalla. Klikkaa luokan kohdalla hiiren oikeaa nappia, valitse refactor ja "extract interface"
- muut riippuvuudet jätetään vielä
-
Määrittele luokalle sopiva konstruktori, jotta voit injektoida riippuvuudet, konstruktorin parametrien tulee olla tyypiltään rajapintoja
-
Muokkaa pääohjelmasi seuraavaan tyyliin:
Kauppa kauppa = new Kauppa(Varasto.getInstance(), Pankki.getInstance(), Viitegeneraattori.getInstance() );
- singleton-suunnittelumallia pidetään osittain ongelmallisena, poistammekin edellisestä tehtävästä singletonit
-
poista kaikista luokista
getInstance
-metodit ja staattineninstance
-muuttuja- joudut muuttamaan luokilla olevat private-konstruktorit julkisiksi
- poista rajapintojen ja dependency injektionin avulla edellisen tehtävän jäljiltä jääneet riippuvuudet, eli
- Varasto --> Kirjanpito
- Pankki --> Kirjanpito
- Muokkaa pääohjelmasi vastaamaan uutta tilannetta, eli suunilleen muotoon:
Kirjanpito kirjanpito = new Kirjanpito();
Varasto varasto = new Varasto(kirjanpito);
Pankki pankki = new Pankki(kirjanpito);
Viitegeneraattori viitegen = new Viitegeneraattori();
Kauppa kauppa = new Kauppa(varasto, pankki, viitegen);
Kuten huomaamme, alkaa kaupan konfigurointi olla aika vaivalloista...
Spring tarjoaa pelastuksen käsillä olevaan tilanteeseen.
Lue nyt sivu Riippuvuuksien-injektointi kohdasta Dependency injection Spring-sovelluskehyksessä loppuun asti
- projektiin on konfiguroitu valmiiksi springin tarvitsemat riippuvuudet, konfiguraatiotiedosto
spring-context.xml
löytyy hakemiston src/main/resources alta (NetBeansissa tämä löytyy kohdan Other Sources -alta) - HUOM mahdolliset virheilmoitukset "org.springframework... package does not exist" katoavat kun buildaat projektin ensimmäisen kerran!
- ota mallia tehtävän 1 ohjeesta ja konfiguroi verkkokauppa Springin xml-muotoista konfiguraatiota siten, että kauppa-olion luominen onnistuu Springin avulla seuraavasti:
public static void main(String[] args) {
ApplicationContext ctx = new FileSystemXmlApplicationContext("src/main/resources/spring-context.xml");
Kauppa kauppa = ctx.getBean(Kauppa.class);
//...
}
Kannattanee edetä tehtävässä pienin askelin siirtäen yksi luokka kerrallaan Springin hallinnoinnin alle
-
HUOM: älä tee tätä edellisen tehtävän päälle, tee projektista kopio
-
tai tee se erilliseen branchiin:
- lue kohta branches osoitteesta http://www.ralfebert.de/tutorials/git/
- tee tälle tehtävälle branch "annotaatiot"
- jotta joku muu branch kuin master (eli "pääbranch") saadaan githubiin, tulee push-komennon olla muodossa git push origin
- palaamme brancheihin tarkemmin ensi viikon tehtävissä
-
muuta edellistä tehtävää siten, että konfigurointi tapahtuu annotaatioiden
@Component
ja@Autowired
avulla -
huom:
- tehtävää ei välttämättä kannata tehdä yhtenä isona askeleena, saattaa olla viistasta muuttaa luokka kerrallaan xml-konfiguraatiosta annotaatiokonfiguroiduksi
- virheilmoitukset eivät ole noviisille selkeimpiä mahdollisa
- muista määritellä
@Component
kaikkiin edellisessä tehtävässä xml:ssä määriteltyihin luokkiin - muista laittaa
@Autowired
jokaiseen luokkaan, jolla on riippuvuuksia
tehtävien kirjaus:
- Kirjaa tekemäsi tehtävät tänne
- huom: tehtävien palautuksen deadline on ma 14.9. klo 23.59
palaute tehtävistä:
- Lisää viikon 1 tehtävässä 11 forkaamasi repositorion omalla nimelläsi olevaan hakemistoon tiedosto nimeltä viikko2
- tee viime viikon tehtävän tapaan pull-request
- anna tehtävistä palautetta avautuvaan lomakkeeseen
- huom: jos teeh tehtävät alkuviikosta, voi olla, että edellistä pull-requestiasi ei ole vielä ehditty hyväksyä ja et pääse vielä tekemään uutta requestia