Erinevus lehekülje "ITI0011:Säuts - koodijuhend" redaktsioonide vahel

Allikas: Kursused
Mine navigeerimisribale Mine otsikasti
26. rida: 26. rida:
  
 
Miks need teenused peavad selliselt eraldi olema? Kas need võiksid ka TwitterApplication'i sees meetoditena olla? Põhimõtteliselt küll. Programmis võib olla asukohapäringu jaoks üks meetod, puhverdamiseks eraldi meetodid jne. Me võime täpselt sama funktsionaalsuse saavutada. Küsimus on aga testimisest. Meetodi testimine on mõnevõrra keerulisem. Ülal näidatud arhitektuuri korral on võimalik testida igat teenust eraldi. Samuti on testimise ajal võimalik mõni teenus välja vahetada. LocationSearch'i asemele paneb testimootor näiteks FakeLocationSearch'i. Sellega saab testida, kas TwitterApplication'i suhtlemine asukohateenusega on korrektne. Kui meetodi korral saame kontrollida meetodi töötamist, siis väga keeruline on testida meetodi väljakutsumist. Eraldi teenuste (ehk siis eraldi klassid, mis on seotud põhiklassiga) puhul on võimalik testida ka klassidevahelist suhtlust.
 
Miks need teenused peavad selliselt eraldi olema? Kas need võiksid ka TwitterApplication'i sees meetoditena olla? Põhimõtteliselt küll. Programmis võib olla asukohapäringu jaoks üks meetod, puhverdamiseks eraldi meetodid jne. Me võime täpselt sama funktsionaalsuse saavutada. Küsimus on aga testimisest. Meetodi testimine on mõnevõrra keerulisem. Ülal näidatud arhitektuuri korral on võimalik testida igat teenust eraldi. Samuti on testimise ajal võimalik mõni teenus välja vahetada. LocationSearch'i asemele paneb testimootor näiteks FakeLocationSearch'i. Sellega saab testida, kas TwitterApplication'i suhtlemine asukohateenusega on korrektne. Kui meetodi korral saame kontrollida meetodi töötamist, siis väga keeruline on testida meetodi väljakutsumist. Eraldi teenuste (ehk siis eraldi klassid, mis on seotud põhiklassiga) puhul on võimalik testida ka klassidevahelist suhtlust.
 +
 +
== Konstruktor ==
 +
 +
Eraldi tuleb rääkida TwitterApplication konstruktorist (täpsemalt siis klassi, mis implementeerib TwitterApplication'it, konstruktorist). Nimelt tuleb selles valmis teha kõik teenuste objektid. Ehk siis asukohaotsing, säutsude otsing jne. Need tuleb salvestada objekti muutujasse, eelistatul läbi setX meetodi (setLocationSearch jne). Peale instantsieerimise (uue objekti loomise) ei tule midagi rohkem teha. Samuti kõik need teenuste objektid, mida te loote, ei tohiks loomise hetkel mingeid päringuid ega muud tegema hakata.
 +
 +
Kui konstruktoris on objektid loodud, siis hiljem pannakse programm käima <code>run</code> meetodiga. Selline jagamine annab testsüsteemil võimaluse näiteks mõni teenus välja vahetada testteenuse vastu. Samuti saab testsüsteem kontrollida mõnda teie teenust eraldi (kuna nüüd on see objekti küljes). Mõnda konkreetselt teenust saaks eraldi testida ka nii, et testsüsteem teeb uue objekti ja testib seda. Selle puhul on keeruline see, et klassi nimetused pole meil fikseeritud. Seega mugavam on lahendada asi nii, et me saame TwitterApplication.getLocationService() meetodiga juba kätte konkreetse instantsi (ehk meil pole vaja new MyLocationService() konstruktorit välja kutsuda, aga sellegipoolest on mul loodud objekt, mis peaks võimaldama päringuid teha).
 +
 +
== Programmi käivitamine ==
 +
 +
Nagu juttu oli, peate looma TwitterApplication interface'i jaoks klassi, mille konstruktor loob teenuste objektid. Programm ise läheb käima selliselt, et loodud objektil kutsutakse välja meetodit <code>run</code>. <code>run</code> on kirjeldatud TwitterApplicationis ära koos sisuga. Vaikimisi (''default'') sisu teeb seda, et vastavalt etteantud argumentide kogusele käivitatakse kas <code>runInteractive()</code> või <code>runWithArgs(args)</code>. Nende sisu tuleb juba teil ise kirjutada. Põhiosas piisab <code>runWithArgs</code> meetodid kirjeldamisest.

Redaktsioon: 28. märts 2015, kell 00:41

Kirjeldus

Siin lehel on kirjeldatud, kuidas koodi kirjutada 2. kodutöö "Säuts" jaoks. Ülesande kirjeldust loe siit (Säuts).

Kui tõmbate alla malli, siis see sisaldab päris mitut interface'i. Interface'id on antud ette seepärast, et meil oleks võimalik teie koodi testida. Teine variant oleks see, et oleksime andnud ette n-ö mallid (klassid), kus peate meetodite sisud ära kirjeldama. Interface on selle jaoks sobiv, kui tahame kokku leppida meetodite nimetuses ja struktuuris. Teie peate looma klassid, mis implementeerivad neid interface'e. Kui kogu ülesande lahendate ära, peaks teil arvatavasti 11 java faili tekkima (lisaks interface'i failidele). Esialgu on nõue, et interface'ide failid oleksid samas kaustas (paketis) kogu ülejäänud lahendusega. Võimalik, et jõuame tehniliselt valmis lahenduse, mis oskaks interface'e ka mujalt otsida.

Nagu selles juhendis näete, on ülesanne jagatud väga väikesteks osadeks. See ei pruugi alati praktiline olla. Kindlasti veendute ise, et selle ülesande lahendamise teeb liigne tükeldamine palju egamugavamaks ja võib-olla isegi ebaloogiliseks. Tükeldamine on aga hea testimise jaoks. Kui teil oleks vaid üks meetod "main", mis saab ette linna nime ja tagastab selles linnas viimased säutsud, siis me saaksime hinnata teie lahendust vaid meetodi väljundi põhjal. Kui te eksite ühe sammuga selles meetodis, on kogu tulemus vale. Automaatselt hinnates võiks tulemus olla 0. Kui me aga jagame ülesande väikesteks tükkideks, saame igat väikest tükki (ehk sammu) eraldi testida. Kui ülejäänud sammud töötavad, viga on ühes sammus, on võimalik kokku saada näiteks 95%. See number on suvaline, aga mõte on ehk arusaadav. Samamoodi on mõistlik päris projektides jagada mingi funktsionaalsus väiksemateks osadeks, et seda testida ning avastada võimalikke vigu.

Arhitektuur

Süsteemiarhitektuur on järgmine.

      main app           (external) service


                     /-- LocationSearch
                    /
TwitterApplication  ---- Cache
                    \
                     \-- TwitterSearch

Põhirakendus on TwitterApplication, selle küljes on erinevad teenused, teenused on eraldi klassid. Analoogselt võib mõelda, et TwitterApplication on nagu reisibüroo, kes vahendab mingeid teenuseid. Näiteks lennuinfot küsitakse mingilt väliselt teenusel mõne lennufirma käest. Hotellide kohta infot saab mõnest hotelliportallist jne. Antud ülesandes kasutatakse teenustena asukohaotsingut, puhverdamist ja säutsude otsimist (mõne boonusülesande korral võib veel selline teenus lisanduda). Kui programm tahab asukoha informatsiooni saada, pöördub see vastava teenuse poole, mis tegeleb konkreetselt sedatüüpi probleemidega.

Miks need teenused peavad selliselt eraldi olema? Kas need võiksid ka TwitterApplication'i sees meetoditena olla? Põhimõtteliselt küll. Programmis võib olla asukohapäringu jaoks üks meetod, puhverdamiseks eraldi meetodid jne. Me võime täpselt sama funktsionaalsuse saavutada. Küsimus on aga testimisest. Meetodi testimine on mõnevõrra keerulisem. Ülal näidatud arhitektuuri korral on võimalik testida igat teenust eraldi. Samuti on testimise ajal võimalik mõni teenus välja vahetada. LocationSearch'i asemele paneb testimootor näiteks FakeLocationSearch'i. Sellega saab testida, kas TwitterApplication'i suhtlemine asukohateenusega on korrektne. Kui meetodi korral saame kontrollida meetodi töötamist, siis väga keeruline on testida meetodi väljakutsumist. Eraldi teenuste (ehk siis eraldi klassid, mis on seotud põhiklassiga) puhul on võimalik testida ka klassidevahelist suhtlust.

Konstruktor

Eraldi tuleb rääkida TwitterApplication konstruktorist (täpsemalt siis klassi, mis implementeerib TwitterApplication'it, konstruktorist). Nimelt tuleb selles valmis teha kõik teenuste objektid. Ehk siis asukohaotsing, säutsude otsing jne. Need tuleb salvestada objekti muutujasse, eelistatul läbi setX meetodi (setLocationSearch jne). Peale instantsieerimise (uue objekti loomise) ei tule midagi rohkem teha. Samuti kõik need teenuste objektid, mida te loote, ei tohiks loomise hetkel mingeid päringuid ega muud tegema hakata.

Kui konstruktoris on objektid loodud, siis hiljem pannakse programm käima run meetodiga. Selline jagamine annab testsüsteemil võimaluse näiteks mõni teenus välja vahetada testteenuse vastu. Samuti saab testsüsteem kontrollida mõnda teie teenust eraldi (kuna nüüd on see objekti küljes). Mõnda konkreetselt teenust saaks eraldi testida ka nii, et testsüsteem teeb uue objekti ja testib seda. Selle puhul on keeruline see, et klassi nimetused pole meil fikseeritud. Seega mugavam on lahendada asi nii, et me saame TwitterApplication.getLocationService() meetodiga juba kätte konkreetse instantsi (ehk meil pole vaja new MyLocationService() konstruktorit välja kutsuda, aga sellegipoolest on mul loodud objekt, mis peaks võimaldama päringuid teha).

Programmi käivitamine

Nagu juttu oli, peate looma TwitterApplication interface'i jaoks klassi, mille konstruktor loob teenuste objektid. Programm ise läheb käima selliselt, et loodud objektil kutsutakse välja meetodit run. run on kirjeldatud TwitterApplicationis ära koos sisuga. Vaikimisi (default) sisu teeb seda, et vastavalt etteantud argumentide kogusele käivitatakse kas runInteractive() või runWithArgs(args). Nende sisu tuleb juba teil ise kirjutada. Põhiosas piisab runWithArgs meetodid kirjeldamisest.