Cpan Liikkuvan Keskiarvon


Tässä luvussa esitellään Perl-moduuleihin, paketteihin ja luokkiin viittaavat käsitteet. Se myös näyttää, kuinka voit luoda muutaman näyte - moduulin. Perl-moduuli on Perl-koodin sarja, joka toimii funktiokutsujen kirjastona. Perl on synonyymi sanapaketille Paketit ovat ominaisuus Perl 4: ssä, kun taas moduulit esiintyvät Perlissä 5. Voit säilyttää kaikki uudelleenkäytettävän Perl-koodisi tiettyihin tehtäviin Perl-moduulissa. Siksi kaikki toiminnot, jotka liittyvät yhteen tyyppiin tehtävä on yhden tiedoston sisällä. Se on helpompi rakentaa sovellus näihin modulaarisiin lohkoihin. Näin sana-moduuli pätee hieman enemmän kuin paketti. Tässä on lyhyt esittely moduuleille. Tietyt tämän kappaleen aiheet käsitellään yksityiskohtaisesti koko muualla kirja Lue tarkasti seuraavat kohdat saadaksesi yleiskuvan siitä, mitä edelle on, kun kirjoitat ja käytät omia moduuleja. Mikä on hämmentävää, että termejä moduulia ja pakettia käytetään interchangeably kaikissa Perl-asiakirjoissa , ja nämä kaksi termiä merkitsevät samaa aihetta. Joten kun luet Perl-dokumentteja, luulet paketin, kun näet moduulin ja päinvastoin. Joten mikä on lähtökohta moduulien käyttämistä varten. Moduulit ovat paketoimalla pun-muuttujia, symboleja , ja yhteenliitetyt tietomäärät yhdessä Esimerkiksi yleisten muuttujien, kuten hyvin tavallisten nimien, kuten kj tai i, käyttäminen ohjelmassa ei yleensä ole hyvä ajatus Myös silmukkaslaskin, minun pitäisi sallia työskennellä itsenäisesti koodin kahdessa eri osassa Ilmoittautuminen i globaaliksi muuttujaksi ja sen lisääminen aliohjelmasta luo sovelluskoodille hallitsemattomia ongelmia, koska aliohjelma on ehkä kutsuttu silmukan sisällä, joka käyttää myös muuttujaa nimeltä i. Perlissä käytettävien moduulien käyttö mahdollistaa muuttujien sama nimi, joka luodaan eri, eri paikoissa samassa ohjelmassa. Muuttujille määritellyt symbolit tallennetaan assosiatiiviseen ryhmään, jota kutsutaan symbolitaulukoksi. s ovat ainutlaatuisia paketeille Siksi samaa nimeä kahdella eri paketilla voi olla eri arvoja. Jokaisella moduulilla on oma symbolitietokanta kaikista tunnuksista, jotka ilmoitetaan sen sisällä. Symbolitaulukko erottaa periaatteessa synonyymejä nimet yhdestä moduulista toiselta. symbolitaulukko määrittelee nimiavaruuden, joka on riippumattomien muuttujien nimet. Näin moduulien käyttö, joista jokaisella on oma symbolitie, estää yhdessä osassa ilmoitetun muuttujan ylikirjoittamasta muiden muuttujien arvoja, joilla on sama nimi muualla samassa ohjelmassa. Itse asiassa kaikki Perl-muuttujat kuuluvat pakettiin Perl-ohjelman muuttujat kuuluvat pääpakettiin Kaikki muut Perl-ohjelman sisältämät paketit joko ovat sisäkkäisiä tässä pääpaketissa tai ovat samaan aikaan taso On olemassa todella globaaleja muuttujia, kuten signaalinkäsittelytilaa SIG, jotka ovat kaikkien muiden sovellusohjelmien moduulien käytettävissä, eikä niitä voi eristää nimiavaruuksien kautta. tai kirjaimista tai aliverkosta alkavia muuttuvia tunnisteita säilytetään moduulin symbolikuvakkeessa Kaikki muut symbolit, kuten nimet STDIN STDOUT STDERR ARGVUT ARGVOUT ENV Inc ja SIG pakotetaan paketoimaan pakettien välillä. Pakkausten välinen yhteys vaikuttaa vain nimiavaruihin Kaikki, tekevät, kun käytät yhtä pakettia tai toinen ilmoittaa, mitä symbolitaulukkoa käytetään oletussymbolitaulukoksi muuttujien nimeämisen etsimiseksi. Vain symbolien taulukot käyttävät vain dynaamisia muuttujia. Avainsanasi ilmoittamat muuttujat ovat edelleen ratkaistu koodijakso, jonka he kohtaavat, eikä niitä viitata symbolitaulukoiden kautta. Itse asiassa paketti-ilmoituksen soveltamisala pysyy aktiivisena vain siinä koodilohkossa, jonka se on ilmoitettu. Siksi, jos vaihdat symbolitaulukoita aliohjelman sisällä olevan paketin avulla, alkuperäisen symbolitaulukon, joka oli voimassa puhelun aikana, palautetaan, kun aliohjelma palaa. Symboli taulukoiden kytkentä vaikuttaa vain dynaamisten variaatioiden oletushakuun ble nimet Voit silti viitata nimenomaisesti muuttujiin, tiedostonhallintaan ja niin edelleen tiettyyn pakettiin esittämällä paketin nimen muuttujan nimeen. Näit, mitä pakettiyhteys oli, kun käytät viitteitä luvussa 3. Paketin yhteydessä tarkoitetaan yksinkertaisesti symbolin taulukko, jonka Perl-tulkki muuttaa muuttujan nimet ohjelmassa Vaihtelemalla symbolit taulukoita, olet vaihtamalla paketin konteksti. Modulit voidaan sisäkkäistää muihin moduuleihin Sisäkkäinen moduuli voi käyttää moduulin muuttujia ja toimintoja, jotka ovat sisäkkäisiä Sisällön moduulit, sinun pitäisi käyttää moduulinName nestedModuleName ja niin edelleen Käyttämällä kaksoispiste on synonyymi käyttäen takaisin lainaus Kuitenkin kaksinkertainen kaksoispiste on paras, tuleva tapa käsitellä muuttujia moduuleissa. Moduulimuuttujien eksplisiittinen osoittaminen tehdään aina täydellinen viite Esimerkiksi oletetaan, että sinulla on moduuli, investointi, joka on käytössäsi oleva oletus paketti ja haluat puuttua toiseen moduuliin, joukkovelkakirjalainat, jotka on sijoitettu sijoittamismoduuliin Tässä tapauksessa et voi käyttää Bondia sen sijaan sinun pitäisi käyttää Investment Bondia käsittelemään muuttujia ja toimintoja Bond-moduulissa Bondin käyttäminen merkitsisi pakettibondin käyttöä, joka on pääyksikössä ja ei investointimoduulissa. Moduulin symbolitietokanta tallennetaan varsinaisesti kahden moduulin osiin liitettyjen moduulien nimet, jotka on liitetty toisiinsa. Bond-moduulin symbolitaulukko kutsutaan assosiaatiorajaksi Bondin nimi taulukko päämoduulille on tärkein ja sitä voidaan jopa lyhentää Samalla tavalla kaikkiin sisäkkäisiin paketteihin on tallennettu niiden symbolit assosiatiivisiin ryhmiin, joissa on kaksoispisteitä, jotka erottavat kukin pesiytymistason. Esimerkiksi sijoittamismoduuliin sisäkkäisessä Bond-moduulissa assosioiva rivi että Bond-moduulin symboleja kutsutaan nimellä Investment Bond. Typeglob on todella globaali tyyppi symbolimäärälle. Voit suorittaa aliastustoiminnot antamalla typeglob Käytetään yksi tai useampia merkintöjä assosiatiiviseen ryhmään symboleille, kun käytetään typeglob: n kautta tehtävää osoitetta Jokaisen assosiatiivisen taulukon jokaisen merkinnän todellinen arvo on se, mitä tarkoitat, kun käytät muuttujan nimitystä. Näin ollen on olemassa kaksi tapaa viittaavat muuttujan nimiin pakettina Sijoitusrahasto Sijoitussummia. Ensimmäisessä menetelmässä olet viittaavat muuttujiin typeglob-viitteen avulla. Symbolitaulukon käyttö, tässä tarkoitetaan sijoitusta, ja Perl optimoi symbolien rahan etsinnän ja laskut Tämä on nopeampi ja edullisempi tapa käsitellä symbolia Toinen menetelmä käyttää etsiä arvoa muuttujan osoittaman rahaa ja laskuja assosiatiivisen taulukon käytetään symboleja, investointi nimenomaan Tämä haku olisi tehtävä dynaamisesti, eikä optimoitu by Perl Siksi haku on pakko tarkistaa assosiatiivisen matriisin joka kerta, kun lausunto toteutetaan. Tämän seurauksena toinen menetelmä ei ole tehokas ja sen pitäisi olla jota käytetään vain demonstroimaan, miten symbolit taulukko toteutetaan sisäisesti. Toinen esimerkki tässä lausunnossa kamran husain. causes muuttujia, aliohjelmia ja tiedoston käsittelee, jotka on nimetty kautta symboli kamran myös käsitellään kautta symboli husain Tämä on kaikki symboli merkinnät nykyisessä symbolitasossa, jossa avain kamran sisältää nyt viittauksia näihin symboleihin, joita avain husain käsittelee. Tällaisen maailmanlaajuisen toimeksiannon estämiseksi voit käyttää selkeitä viitteitä. Esimerkiksi seuraavan lauseen avulla voit käsitellä husainin sisältöä muuttujan kamran kamran husain. Kaikki taulukot, kuten kamran ja husain, eivät ole samat Vain ne, jotka viitataan nimenomaisesti, muuttuvat Yhteenvetona, kun annat yhden typeglobin toiselle, vaikuttaa kaikkiin merkintöihin taulukossa taulukosta riippumatta muuttujasta, johon viitataan Kun määrität viittauksen yhdestä muuttujan tyypistä toiseen, kosketat vain yhtä merkkiä symbolitaulukossa. Perl-moduuli tiedostomuodossa on seuraava muotoilupaketti ModuuliNimi Lisää moduulikoodi 1. Tiedostonimi on nimeltään Moduulin nimi on päättyvä merkkijonoon sopivaksi Paketin lauseke on tiedoston ensimmäinen rivi Tiedoston viimeisen rivin on sisällettävä rivi 1-lausekkeella Tämä palauttaa todellisen arvon sovellusohjelmaan moduulin avulla. Ei-1-lauseen antaminen ei anna moduulin ladata oikein. Paketin lausunto kertoo, että Perl-tulkki aloittaa uuden nimiavaruussymbolin kanssa. muuttujat ovat Perl-skriptiä, joka kuuluu pakettiin nimeltä main. Jokaisen päätietokannan muuttujaa voidaan kutsua päämuuttujaksi. Sellaisen referenssin syntaksin pakettiName muuttujaName. Yksittäinen lainaus on synonyymi kaksoispiste-operaattorille. operaattorin seuraavassa luvussa Toistaiseksi on muistettava, että seuraavat kaksi lauseketta ovat samanlaisia ​​pakettiName muuttujaName pakettiName muuttujaName. kaksoispisteinä sy ntax pidetään vakiona Perl-maailmassa Siksi luettavuuden säilyttämiseksi käytän kaksoispiste-syntaksia tämän kirjan loppuosassa, ellei se ole ehdottoman välttämätöntä tehdä poikkeuksia pisteiden todentamiseksi. nykyinen paketti, joka on aktiivinen kokoamisen ajankohtana. Jos olet pakettina ja määritä muuttuja pv, muuttuja on itse asiassa yhtä kuin Finance pv. Käyttämällä Perl-moduuleja käytä vs require. You sisällyttävät Perl-moduuleja ohjelmassasi käyttämällä vaativat lauseketta Tässä käytetään tapaa käyttää kumpaakaan lauseketta ModuleName edellyttää ModuleName. Nota että laajennusta ei käytetä edellä esitetyssä koodissa Huomaa myös, että kumpikaan lauseke ei salli tiedostojen sisällyttämistä ohjelmaan useammin kuin kerran. true 1, koska viimeinen lausunto on tarpeen, jotta Perl tietää, että vaatimus d tai käyttää d-moduulia ladattu oikein ja antaa Perl-tulkki ohittaa uudelleenlataukset Yleensä on parempaa käyttää moduulin lauseketta kuin e vaativat Perl-ohjelman Module-lauseketta pysymään yhteensopivina Perl. For-moduulien tulevien versioiden kanssa, sinun kannattaa harkita jatkossakin käyttämään vaatimuslauseketta. Tässä syystä käyttölausunto tekee hieman enemmän työtä kuin vaativat lausunto, koska se muokkaa moduulin nimitilaa, joka sisältää toisen moduulin Haluat tämän ylimääräisen päivityksen tekemisen nimeämisohjelmassa Kun kirjoitat koodia moduulille, et välttämättä halua muuttaa nimetilaa, ellei sitä nimenomaisesti vaadita Tässä tapauksessa , käytät vaatimus-lauseketta. Vaatimuslausekkeessa on Inc-taulukon tiedoston koko polunimi, niin että moduulin s tiedoston toiminnot ja muuttujat ovat tunnetussa paikassa toteutusaikana. Siksi toiminnot, jotka tuodaan moduuli tuodaan nimenomaisella moduulirenkaalla rytmissä vaadittavasta lausekkeesta Käyttölausunto on sama kuin vaatimus, koska se päivittää Inc-taulukon täydellä polulla kuormitettujen moduulien nimet Käyttöfunktiokoodi menee myös askeleen eteenpäin ja kutsuu tuoda-toimintoa moduulissa, jossa käytetään d eksplisiittisesti ladata vietyjen toimintojen luetteloa koottua aikaa, jolloin säästyy aikaa, joka tarvitaan toiminnon eksplisiittiselle resoluutiolle nimi käyttötarkoituksen aikana. Odotuslauseke vastaa vaatimusta ModuleName-tuodusta ModuleName-luettelosta tuoduista funktioista. Käyttötarkoituksen käyttäminen muuttaa ohjelman n nimiavaruutta, koska tuotujen toimintojen nimet lisätään symbolikenttään. Vaatimuslauseke ei muuta ohjelman n nimiavaruus Tämän vuoksi seuraava lausuma käyttää ModuleName. is: tä, joka vastaa tätä lauseketta, edellyttää, että ModuleName. Functions tuodaan moduulista puhelun kautta tuonnin funktiona. Voit kirjoittaa oman tuontitoiminnon moduuliin tai voit käyttää Vienti-moduuli ja sen tuontitoiminto Useimmissa tapauksissa käytät Exporter-moduulia tuodaksesi tuontitoiminnon uudelleen keksimisen sijasta pyörä Voit oppia lisää tästä seuraavassa osassa Jos päätät olla käyttämättä Exporter-moduulia, sinun on kirjoitettava oma tuontitoiminto jokaisessa kirjoittamasi moduulissa. Se on paljon helpompaa yksinkertaisesti käyttää Exporter-moduulia ja antaa Perl Tee työtä sinulle. Näytteen moduuli. Paras tapa havainnollistaa modulaatin modulaattimallin käyttämistä Perlissä on kirjoittaa yksinkertainen moduuli ja näyttää sen käyttäminen. Otetaan esimerkki paikallisesta lainahaasta, Rudious Maximus , joka on yksinkertaisesti kyllästynyt kirjoittamaan samaa maksupyyntöä. Se on innokas tietokone - ja Perl-fani. Rudious ottaa laiska-ohjelmoijan lähestymistavan ja kirjoittaa Perl-moduulin auttamaan häntä luomaan muistelmansa ja kirjeitään. Nyt kentän kirjoittamisen sijasta joka on kirjoitettava muutaman rivin tuottamaan mukavaa, uhkaavaa huomata Listing 4 1 näyttää, mitä hänen on kirjoitettava Listing 4 1 Letter-moduulin 1 usr bin perl - w 2 3 Pois alla olevan rivin sisällyttämiseksi Inc 4 push Inc: iin , pwd 5 6 Käytä kirjainta 7 8 Letter to Mr Gambling Man, Rahat Lucky Dogille, kilpailu 2 9 Letter ClaimMoneyNice 10 Letter ThankDem 11 Letter Finish. Käytä Letter-lausunto on olemassa pakottamaan Perl-tulkki sisällyttämään moduulin koodi sovellusohjelmassa Moduulin pitäisi sijaita usr lib perl5 - hakemistossa tai voit sijoittaa sen mihin tahansa Inc-taulukossa mainittuun hakemistoon. Inc-taulukko on luettelo hakemistoista, joita Perl-tulkki etsii yritettäessä ladata koodia nimetylle moduulille Kommentoidut rivinumero 4 näyttää, miten nykyinen työhakemisto lisätään polkuun. Tiedoston neljä seuraavaa riviä muodostavat kirjeen aiheen. Tällöin Letter-moduulin lähdön arvo on Mr Gambling Man Fm Rudious Maximus, Loan Shark Dt Wed Helmikuu 7 10 35 51 CST 1996.Re Rahat Lucky Dogille, kilpailu 2.It on tullut huomaan, että tilisi on aivan liian myöhään Sinä maksat meille pian Tai haluatko minun tulevan äiti. Kiitos tuki. Letter-moduulitiedosto näkyy luettelossa 4 2 Paketin nimi ilmoitetaan ensimmäisellä rivillä Koska tämän moduulin toiminnot viedään, käytän Exporter-moduulia. Siksi lauseen käyttäminen Exporterin on perittävä toimintoja Vienti-moduuli Toinen vaadittu vaihe on viedä sanan ISA-taulukon vietävä jotta hakua voidaan hakea. ISA-taulukko on erityinen taulukko jokaisessa paketissa Jokainen taulukon kohde näyttää, mistä muualla etsitään menetelmää, jos sitä ei löydy nykyisestä paketti Tilaus, jossa paketit on lueteltu ISA-taulukossa, on järjestys, jossa Perl etsii ratkaisemattomia symboleja Luokka, joka on lueteltu ISA-ryhmässä, kutsutaan kyseisen tietyn luokan perusluokaksi Perl välittää puuttuvat menetelmät, jotka löytyvät alustasta luokat tulevia viitteitä varten ISA-taulukon muokkaus huuhtelee välimuistin ja aiheuttaa Perlille mahdollisuuden etsiä kaikkiin menetelmiin uudelleen. Katsokaa nyt koodia luettelossa 4 2 Listat 4 2 Moduulin 1 paketti Letter 2 3 vaatia Exporter 4 ISA Exporter 5 6 head1 NIMI 7 8 Letter - näytemoduuli, joka luo sinulle kirjelomakkeen 9 10 head1 SYNOPSIS 11 12 käytä kirjainta 13 14 kirjeen päivämäärä 15 kirjain Nimi, yritys, osoite 16 17 Sitten yksi seuraavista 18 Letter ClaimMoneyNice 19 Letter ClaimMoney 20 Letter ThreatBreakLeg 21 22 Letter ThankDem 23 Letter Finish 24 25 head1 KUVAUS 26 27 Tämä moduuli tarjoaa lyhyen esimerkin kirjeen luomisesta 28 ystävälliselle naapurimaiden lainan hainille 29 30 Koodi alkaa leikkausosan 31 leikkauksen jälkeen 32 33 EXPORT qw Päivämäärä, 34 To, 35 ClaimMoney, 36 ClaimMoneyNice, 37 Kiitos, 38 Maali 39 40 41 Tulosta tänään päivä 42 43 sub Letter päivä 44 date date 45 print n Tänään on päivämäärä 46 47 48 sub Kirje 49 paikalliseen nimenmuutokseen 50 paikallisen aiheen siirto 51 tulostus n Nimikkeen 52 tulostus n Fm Rudious Maximus, Loan Shark 53 tulostus n Dt, päiväys 54 print n Aiheet 55 print nn 56 print nn 57 58 sub Letter ClaimMoney 59 print n Sinä velkaa minulle rahaa yhdessä 60 tulosta n Haluatko lähettää Brunoon 61 tulostukseen n kerätä tai maksaa 62 63 64 sub Letter ClaimMoneyNice 65 print n On tullut huomaan, että tilisi on 66 tulostus n tavalla yli 67 print n You maksaa meille pian 68 tulosta n tai haluaisit minun tulevan munasolun 69 70 71 sub Letter ThreatBreakLeg 72 tulosta n näennäisesti tällaisia ​​kirjeitä ei auta 73 print n Minun on tehtävä esimerkki teistä 74 print nn Nähdään sairaalassa , pal 75 76 77 sub Kirje Thanksdem 78 print nn Kiitos tuesta 79 80 81 sub Letter Finish 82 printf nnnn Ystävällisin terveisin 83 printf n Vanha n 84 85 86 1.Laitteita, jotka sisältävät yhtäläisen merkin, käytetään asiakirjoissa Sinun on dokumentoitava jokainen moduuli Perl-moduuleja ei tarvitse dokumentoida, mutta sinun on hyvä kirjoittaa muutama rivi siitä, mitä koodisi tekee. Muutama vuosi sitten voit unohtaa, mitä moduuli koskee. Hyvä dokumentaatio on aina tarpeen, jos haluat muistaa, mitä teit aiemmin Perlissä käytettävät dokumentaatiotyypit luvussa 8 Perl-komentotiedostojen dokumentointi Tässä esimerkkimodulissa head1-lauseke alkaa dokumentaatiosta Perl-tulkki jättää kaiken leikkaus-lauseen huomiotta. Seuraavaksi moduuli listaa kaikki tämän moduulin EXPORT-ohjelmassa vievät toiminnot array EXPORT-taulukko määrittää kaikki toiminnot, jotka voidaan kutsua ulkoisella koodilla. Jos et esitä mitään toimintoa EXPORT-ryhmässä, sitä ei voitu nähdä ulkoisilla koodimoduuleilla. EXPORT-taulukko on koodin elin, yksi aliohjelma kerrallaan Kun kaikki aliohjelmat on määritetty, lopullinen lausuma 1 päättyy moduulitiedoston 1 on oltava viimeinen suoritettava linja tiedostossa. Katsokaa joitakin tässä moduulissa määritettyjä toimintoja. Ensimmäinen tarkasteltava toiminto on yksinkertainen päivämäärätoiminto, rivit 43-46, joka tulostaa nykyisen UNIX-päivämäärän ja ajan Tämän toiminnon parametreja ei ole ja se ei palauta mitään merkityksellistä takaisin soittajalle. Kuitenkin ennen päivämäärää var iable rivillä 44 My avainsanaa käytetään rajoittamaan muuttujan ulottuvuus Date-toiminnossa oleviin kiharaisiin solmukkeisiin Koodin välisten koukkujen välistä koodia kutsutaan lohkoksi. Lohkossa ilmoitetut muuttujat ovat rajoitettuja ulottuvuudelle kipeästi varustetuissa kohokohdissa 49 ja 50, paikalliset muuttujat nimi ja aihe ovat näkyvissä kaikille funktioille. Voit myös ilmoittaa muuttujat paikallisen karsintatyypin kanssa. Paikallien käyttö sallii muuttujan olevan voimassa nykyiselle lohkolle samoin kuin muille, tämä lohko Näin lohkon sisällä ilmoitettu paikallinen x on näkyvissä kaikille seuraaville lohkoille, jotka on kutsuttu tämän lohkon sisällä ja joita voidaan viitata Seuraavassa esimerkkikoodissa voidaan käyttää ToTitled-funktiota n nimimuuttujaa, mutta ei tietoja iphone 1: n aliryhmässä ToTitled 2 paikallisnimi 3 siirto puhelimelle. Näytteenkoodi osoitti, miten yhden parametrin otettaisiin kerrallaan Aliohjelma Tee kaksi parametria otsikon asettamiseksi muistille. Moduulin käyttämät toiminnot ovat n mikä tahansa muu kuin Perl-moduulien käyttäminen ja määrittäminen samassa kooditiedostossa Parametrit ohjataan viitteellisesti, ellei toisin ole määritelty. Aliohjelmalle siirretyt moniryhmät, ellei niitä nimenomaisesti ole poistettu, ovat ketjutettuja. Syöttöryhmä toiminnassa on aina taulukko Scalar-arvot Arvojen ylittäminen referenssinä on Perlissä edullinen tapa siirtää suuria määriä dataa aliohjelmaan Katso luku 3 Viitteet. Toinen esimerkkimodulin rahoitus. Rahoituksen moduuli, joka on esitetty luettelossa 4 3, käytetään yksinkertaisten laskelmien tekemiseen laina-arvot Rahoitus-moduulin käyttäminen on yksinkertaista Kaikki toiminnot kirjoitetaan samoilla parametreilla, kuten funktion kaavasta näkyy. Tarkastellaan miten sijoituksen tuleva arvo voidaan laskea Esimerkiksi jos sijoitat jonkin verran dollareita, pv joukkovelkakirjalaina, joka tarjoaa kiinteän prosenttiosuuden, r sovelletaan tunnetuin väliajoin n ajanjaksolle, mikä on joukkovelkakirjan arvo sen erääntymishetkellä. jos käytät seuraavaa kaavaa fv pv 1 r n. Toiminto tulevaisuuden arvon saamiseksi ilmoitetaan FutureValue-nimikkeeksi Katso lista 4 3, miten sitä käytetään. Listing 4 3 Finance-moduulin käyttäminen 1 usr bin perl - w 2 3 push Inc, pwd 4 käyttää Rahoitus 5 6 laina 5000 00 7 huhti 3 5 huhtikuu 8 vuosi 10 vuotta 9 10 ------------------------ ---------------------------------------- 11 Laske arvo lainan lopussa jos korkoa 12 sovelletaan vuosittain 13 ------------------------------------------ ---------------------- 14 aika 15 fv1 Rahoitus FutureValue-laina, huhti, aika 16 print n Jos korkoa sovelletaan vuoden lopussa 17 print n Tulevaisuus arvo laina n 18 tulostetaan APR: ssä, huhtikuu, aika, vuodet 19 printf on 8 2f n fv1 20 21 --------------------- ------------------------------------------- 22 Laske arvo lopussa lainaa, jos korkoa 23 sovelletaan kuukausittain 24 --------------------------------------- ------------------------- 25 nopeus apr 12 huhtikuu 26 aika kyllä r 12 kuukausina 27 fv2 Rahoitus FutureValue-laina, korko, aika 28 29 print n Jos korkoa sovelletaan jokaisen kuukauden lopussa 30 print n Lainan 31 lainan tulevaa arvoa tulostetaan huhtikuun, huhtikuu, kuukautta 32 printf on 8 2f n fv2 33 34 printf n Arvon ero on 8 2f, fv2 - fv1 35 printf n Siksi soveltamalla kiinnostusta lyhyemmillä aikajaksoilla 36 printf n olemme todella saada enemmän rahaa kiinnostaa n. Here on näyte panos ja tuotos 4 3 testme. Jos korkoa sovelletaan vuoden lopussa Tuleva arvo 5000 lainaa 3 5 vuosipäivänä 10 vuoden ajan on 7052 99. Jos korkoa sovelletaan kunkin kuukauden lopussa Tuleva arvo 5000: n lainaa 3 5: n vuosikoron 120 kuukauden ajan on 7091 72. Arvon ero on 38 73 Siksi korottamalla korkoa lyhyemmillä ajanjaksoilla olemme todella saaneet lisää rahaa korkoihin. Tuloksena on tulos arvojen vertaamisesta fv1: n ja fv2: n välillä Fv1-arvo lasketaan soveltamalla i: tä nterest kerran vuodessa joukkovelkakirjalainan jaksolla fv2 on arvo, jos korkoa sovelletaan kuukausittain vastaavan kuukausikoron mukaan. Pakkaus on listattu 4 4 sen varhaisessa kehitysvaiheessa Listing 4 4 Paketti 1 paketti Finance 2 3 vaativat Exporter 4 ISA Exporter 5 6 head1 7 8 Financial Calculator - Perl 9 10 - periaatteella tehdyt taloudelliset laskelmat 11 Rahoitus 12 13 pv 10000 0 14 15 korkokanta 12 5 12 kk kuukaudessa 16 17 kk 360 kk laina 18 19 fV FutureValue 20 21 tulostaa fv 22 23 leikkaus 24 25 EXPORT qw FutureValue, 26 PresentValue, 27 FVofAnnuity, 28 AnnuityOfFV, 29 getLastAverage, 30 getMovingAverage, 31 SetInterest 32 33 34 Globals, jos on 35 36 37 paikallista defaultInterest 5 0 38 39 sub Finanssi SetInterest 40 my rate shift 41 defaultInterest rate 42 printf n defaultInterest rate 43 44 45 -------------------------------- ------------------------------------ 46 Liitetiedot 47 1 Korko r on arvoltaan 0-100 48 2 n annettuna vuonna ehdot ovat korko, jolla korkoa 49 sovelletaan 50 51 ------------------------------------ -------------------------------- 52 53 ---------------- -------------------------------------------------- - 54 Sijoituksen nykyarvo 55 fv - tuleva arvo 56 r - korko kaudesta 57 n - ajanjakso 58 ---------------------- ---------------------------------------------- 59 sub Finance FutureValue 60 minun pv, r, n 61 minun fv pv 1 r 100 n 62 palaa fv 63 64 65 ----------------------------- --------------------------------------- 66 Sijoituksen nykyarvo 67 fv - a tuleva arvo 68 r - korko kaudesta 69 n - ajanjakso 70 ----------------------------------- --------------------------------- 71 sub Talous PresentValue 72 minun pv 73 minun fv, r, n 74 pv fv 1 r 100 n 75 paluupäivä 76 77 78 79 --------------------------------------- ----------------------------- 80 Hanki ansioluettelon tuleva arvo 81 mp - Kuukausittainen ansiomaksun maksu 82 r - aika 8 3 n - ajanjakso 84 ------------------------------------------- ------------------------- 85 86 sub FVofAnnuity 87 minun fv 88 my oneR 89 my mp, r, n 90 91 oneR 1 rn 92 fv mp oneR - 1 r 93 paluu 94 94 96 ---------------------------------------- ---------------------------- 97 Hanki elinkorvaus seuraavista tietopisteistä 98 r - korko kaudesta 99 n - ajanjakso 100 fv - Tulevaisuuden arvo 101 -------------------------------------------- ------------------------ 102 103 sub AnnuityOfFV 104 my mp mp - Annuityn kuukausimaksu 105 my oneR 106 my fv, r, n 107 108 oneR 1 rn 109 mp fv r oneR - 1 110 paluuta mp 111 112 113 ----------------------------------- --------------------------------- 114 Hanki viimeisten n arvojen keskiarvo taulukossa 115 ---- -------------------------------------------------- -------------- 116 Taulukon elementtien viimeinen lukumäärän arvo arvoissa 117 Arvojen elementtien kokonaismäärä lukumäärissä 118 119 sub getLastAverage 120 my count, n umber, arvot 121 my i 122 123 my a 0 124 paluu 0 jos määrä 0 125 i 0 i laske i 126 a arvot numero i i 1 127 128 palauta numero 129 130 131 ---------- -------------------------------------------------- -------- 132 Saat arvojen liukuvan keskiarvon 133 --------------------------------- -------------------------------------------------- 134 Näytön koko on ensimmäinen parametri, 135 siirretty matriisi on seuraava Tämä voidaan helposti laskea 136: n funktion sisällä skalaaritoiminnolla, mutta tässä esitettyä aliohjelmaa 137 käytetään myös havainnollistamaan kuinka siirtää osoittimia Viittaus arvoihin 138 viedään seuraavaksi, jota seuraa viittaus paikkaan 139 paluuarvot on tallennettava 140 141 sub getMovingAve 142 lukuarvoni, numero, arvot, liikkuva 143 minun i 144 my a 0 145 my v 0 146 147 palaa 0 jos count 0 148 return -1 if count number 149 paluu -2 jos määrä 2 150 151 liikkuvaAve 0 0 152 liikkuvaAve numero - 1 0 153 i 0 i lasketaan i 154 v arvot i 1 55 av numero 156 liikkuvaAve i 0 157 158 i laskea i luku i 159 v arvot i 160 av numero 161 v arvot i - count - 1 162 a - v count 163 movingAve ia 164 165 return 0 166 167 168 1.Näytä funktiota koskeva ilmoitus FutureValue jossa kolme dollarin merkkiä yhdessä merkitsevät kolmea skalaarilukuja, jotka siirretään funktioon Tämä ylimääräinen raja-arvo on läsnä funktiolle siirrettyjen parametrien tyypin validoimiseksi Jos joudut siirtämään merkkijonon numeron sijaan funktioon , saat viestin, joka on hyvin samankaltainen kuin tämä. Liian monet argumentit Finance FutureValue - ohjelmaan rivillä 15 lähellä aikaa Kokoonpanovirheiden vuoksi suoritettu keskeytys. Prototyyppien käyttö määritettäessä toimintoja estää sinua lähettämästä muita arvoja kuin mitä funktio odottaa Käytä tai siirrä arvoryhmiä Jos käytät viittausta, käytä tai näytä skalaarin viittaus taulukkoon tai hash-arvoon. Jos et käytä paluuta, kaikki muut argumenttiluettelon prototyypit ovat ei ole otettu huomioon Muut poikkeustyypit sisältävät mainoksen, joka sisältää toiminnon viitenumeron, minkä tahansa tyyppisen tähdet ja puolipisteet, jotka osoittavat, että kaikki muut parametrit ovat valinnaisia. Nyt katsotaan viimeisinMovingAverage-toimintoilmoituksen, jossa määritetään kaksi kokonaislukua edessä, jota seuraa taulukko Tapa, jolla argumentteja käytetään funktiossa, on määrittää arvo kahteen skalaariin, laskuun ja numeroon, kun taas kaikki muut lähetetään taulukkoon Katso funktiota getMovingAverage nähdäksesi, kuinka kaksi ryhmää siirretään jotta saadaan liukuva keskiarvo arvoluettelossa. Esimerkki: getMovingAverage-toiminnon soittaminen näkyy luettelossa 4 5 Listalle 4 5 Liikkuva keskimääräinen toiminto 1 usr bin perl - w 2 3 push Inc, pwd 4 käytä Finance 5 6 arvot 12,22,23,24,21,23,24,23,23,21,29,27,26,28 7 mv 0 8 skalaarin arvot 9 tulosta n Arvot työskennellä n 10 tulosta Arvoarvojen lukumäärä n 11 12 ------------------------------------------------ ---------------- 13 Laske a edellä mainitun funktion verage 14 -------------------------------------------- -------------------- 15 ave Rahoitus getLastAverage 5, koko, arvot 16 print n 5 viikon keskimäärin ave n 17 18 Rahoitus getMovingAve 5, koko, arvot, mv 19 print n Siirrä keskimäärin 5 päivän ikkuna n n. Katso listan tuotto 4 5 Arvot toimimaan Arvojen lukumäärä 14. Viimeisen 5 päivän keskiarvo 26 2. getMovingAverage-funktio ottaa kaksi skalaaria ja sitten kaksi viittausta taulukkoihin skalaarit Toiminnossa taulukon kaksi skalaaria ohjataan käytettäväksi numeerisina ryhminä Palautettu arvoryhmä sijoitetaan siirrettyyn alueeseen toisena viitejoukona Jos syöttöparametreja ei ole määritetty kullekin viitavalle ryhmälle, liikkuvan Ave-matriisin viittaus olisi ollut tyhjää ja olisi aiheuttanut virheitä suoritusaikana. Toisin sanoen seuraava ilmoitus ei ole oikea sub getMovingAve. Tuloksena oleva spew virheilmoituksista huono toiminnon prototyypistä on seuraavanlainen Käyttämättömät arvo rivillä 128 Käyttämättömän arvon käyttäminen rivillä 128 Käyttämättömän arvon käyttäminen rivillä 128 Käyttämättömän arvon käyttäminen rivillä 128 Käyttämättömän arvon käyttäminen rivillä 128 Käyttämättömän arvon käyttäminen rivillä 133 Käyttämättömän arvon käyttäminen rivillä 135 Käyttämättömän arvon käyttö rivillä 133 Käyttämättömän arvon käyttäminen rivillä 135 Käyttämättömän arvon käyttäminen rivillä 133 Käyttämättömän arvon käyttö rivillä 135 Käyttämättömän arvon käyttäminen rivillä 133 Käyttämättömän arvon käyttö rivillä 135 Käyttämättömän arvon käyttäminen rivillä 133 Käyttämättömän arvon käyttäminen kohdassa 135 linja 135 Käyttämättömän arvon käyttäminen rivillä 133 Käyttämättömän arvon käyttäminen rivillä 135 Käyttämättömän arvon käyttäminen rivillä 133 Käyttämättömän arvon käyttäminen rivillä 135 Käyttämättömän arvon käyttäminen rivillä 133 Käyttämättömän arvon käyttö rivillä 135 Käyttämättömän arvon käyttäminen rivillä 133 Käyttämättömän arvon käyttäminen rivillä 135. Viimeksi kuluneiden 5 päivän keskiarvo 26 2. Siirtyminen keskimäärin 5 päivän ikkuna. Tämä ei selvästikään ole oikea tuotos. Siksi se on kriittinen että siirryt viitteellesi lähetettäessä useampaa kuin yhtä taulukkoa. Myös pakettien sisällä käytettäviä globaaleja muuttujia voidaan julistaa. Katso moduulilta koodin seuraava segmentti nähdäksesi, mikä korkomuuttujan oletusarvo olisi, jos mitään ei määritetty syötteessä Nykyinen moduuli vaatii kiinnostuksen läpäisemisen, mutta voit muuttaa tätä. Tässä on pieni koodinpätkä, joka voidaan lisätä luettelossa 4 5 esitetyn ohjelman loppuun lisätäksesi mahdollisuutta asettaa korkotaso 20 paikallinen defaultInterest 5 0 21 sub Finance SetInterest 22 my rate shift 23 rate -1 if rate 0 24 defaultInterest rate 25 printf n defaultInterest rate 26. Paikallinen muuttuja defaultInterest ilmoitetaan rivillä 20 Subreuutiossa SetInterest muutetaan nopeutta ilmoitetaan riveillä 21 through 26 The rate variable uses the values passed into the subroutine and simply assigns a positive value for it You can always add more error checking if necessary. To access the defaultInterest variable s value, you could define either a subroutine that returns the value or refer to the value directly with a call to the following in your application program Finance defaultInterest. The variable holding the return value from the module function is declared as my variable The scope of this variable is within the curly braces of the function only When the called subroutine returns, the reference to my variable is returned If the calling program uses this returned reference somewhere, the link counter on the variable is not zero therefore, the storage area containing the returned values is not freed to the memory pool Thus, the function that declares my pv. and then later returns the value of pv returns a reference to the value stored at that location If the calling routine performs a call like this one Finance FVofAnnuity monthly, rate, time. there is no variable specified here into which Perl stores the returned reference therefore, any returned value or a list of values is destroyed Instead , the call with the returned value assigned to a local variable, such as this one fv Finance FVofAnnuity monthly, rate, time. maintains the variable with the value Consider the example shown in Listing 4 6, which manipulates values returned by functions Listing 4 6 Sample usage of the my function 1 usr bin perl - w 2 3 push Inc, pwd 4 use Finance 5 6 monthly 400 7 rate 0 2 i e 6 APR 8 time 36 in months 9 10 print n ------------------------------------------------ 11 fv Finance FVofAnnuity monthly, rate, time 12 printf n For a monthly 8 2f at a rate of 6 2f for d periods , 13 monthly, rate, time 14 printf n you get a future value of 8 2f , fv 15 16 fv 1 1 allow 10 gain in the house value 17 18 mo Finance AnnuityOfFV fv, rate, time 19 20 printf n To get 10 percent more at the end, i e 8 2f , fv 21 printf n you need a monthly payment value of 8 2f , mo, fv 22 23 print n ------------------------------------------------ n. Here is sample input and output for this function testme ---------- -------------------------------------- For a monthly 400 00 at a rate of 0 20 for 36 periods you get a future value of 1415603 75 To get 10 percent more at the end, i e 1557164 12 you need a monthly payment value of 440 00.Modules implement classes in a Perl program that uses the object-oriented features of Perl Included in object-oriented features is the concept of inheritance You ll learn more on the object-oriented features of Perl in Chapter 5 Object-Oriented Programming in Perl Inheritance means the process with which a module inherits the functions from its base classes A module that is nested within another module inherits its parent modules functions So inheritance in Perl is accomplished with the construct Here s the basic syntax SuperClass NextSubClass ThisClass. The file for these is stored in SuperClass NextSubClass Each double colon indicates a lower-level directory in which to look for the module Each module, in turn, declares itself as a package with statements like the f ollowing package SuperClass NextSubClass package SuperClass NextSubClass EvenLower. For example, say that you really want to create a Money class with two subclasses, Stocks and Finance Here s how to structure the hierarchy, assuming you are in the usr lib perl5 directory. Create a Money directory under the usr lib perl5 directory. Copy the existing file into the Money subdirectory. Create the new file in the Money subdirectory. Edit the file to use the line package Money Finance instead of package Finance. Edit scripts to use Money Finance as the subroutine prefix instead of Finance. Create a file in the usr lib perl5 directory. The Perl script that gets the moving average for a series of numbers is presented in Listing 4 7 Listing 4 7 Using inheriting modules 1 usr bin perl - w 2 aa pwd 3 aa Money 4 push Inc, aa 5 use Money Finance 6 values 12,22,23,24,21,23,24,23,23,21,29,27,26,28 7 mv 0 8 size scalar values 9 print n Values to work with n 10 print Number of values size n 11 -------- -------------------------------------------------------- 12 Calculate the average of the above function 13 ---------------------------------------------------------------- 14 ave Money Finance getLastAverage 5, size, values 15 print n Average of last 5 days ave n 16 Money Finance getMovingAve 5, size, values, mv 17 foreach i values 18 print n Moving with 5 days window mv i n 19 20 print n Moving Average with 5 days window n n. Lines 2 through 4 add the path to the Money subdirectory The use statement in line 5 now addresses the file in the Money subdirectory The calls to the functions within are now called with the prefix Money Finance instead of Finance Therefore, a new subdirectory is shown via the symbol when Perl is searching for modules to load. The file is not required Even so, you should create a template for future use Actually, the file would be required to put any special requirements for initialization that the entire hierarchy of modules uses The code for initialization i s placed in the BEGIN function The sample file is shown in Listing 4 8 Listing 4 8 The superclass module for 1 package Money 2 require Exporter 3 4 BEGIN 5 printf n Hello Zipping into existence for you n 6 7 1.To see the line of output from the printf statement in line 5, you have to insert the following commands at the beginning of your Perl script use Money use Money Finance. To use the functions in the module, you use this line use Money Stocks. The file appears in the Money subdirectory and is defined in the same format as the file, with the exceptions that use Stocks is used instead of use Finance and the set of functions to export is different. A number of modules are included in the Perl distribution Check the usr lib perl5 lib directory for a complete listing after you install Perl There are two kinds of modules you should know about and look for in your Perl 5 release, Pragmatic and Standard modules. Pragmatic modules, which are also like pragmas in C compiler directives, tend to affect the compilation of your program They are similar in operation to the preprocessor elements of a C program Pragmas are locally scoped so that they can be turned off with the no command Thus, the command no POSIX. turns off the POSIX features in the script These features can be turned back on with the use statement. Standard modules bundled with the Perl package include several functioning packages of code for you to use Refer to appendix B, Perl Module Archives, for a complete list of these standard modules. To find out all the modules installed on your system, issue the following command If you get an error, add the usr lib perl5 directory to your path find usr lib perl5 - name perl - print. Extension modules are written in C or a mixture of Perl and C and are dynamically loaded into Perl if and when you need them These types of modules for dynamic loading require support in the kernel Solaris lets you use these modules For a Linux machine, check the installation pages on how to upgr ade to the ELF format binaries for your Linux kernel. The term CPAN Comprehensive Perl Archive Network refers to all the hosts containing copies of sets of data, documents, and Perl modules on the Net To find out about the CPAN site nearest you, search on the keyword CPAN in search engines such as Yahoo AltaVista, or Magellan A good place to start is the site. This chapter introduced you to Perl 5 modules and described what they have to offer A more comprehensive list is found on the Internet via the addresses shown in the Web sites and. A Perl package is a set of Perl code that looks like a library file A Perl module is a package that is defined in a library file of the same name A module is designed to be reusable You can do some type checking with Perl function prototypes to see whether parameters are being passed correctly A module has to export its functions with the EXPORT array and therefore requires the Exporter module Modules are searched for in the directories listed in the Inc array. Obviously, there is a lot more to writing modules for Perl than what is shown in this chapter The simple examples in this chapter show you how to get started with Perl modules In the rest of the book I cover the modules and their features, so hang in there. I cover Perl objects, classes, and related concepts in Chapter 5.CPAN is in the industry standards, technical specifications and software library and framework skills category The next table is for comparison with the above and provides summary statistics for all permanent job vacancies with a requirement for industry standards, technical specifications and software library and framework skills. Software Library Framework Skills. Permanent job vacancies with a requirement for industry standards, technical specifications and software library and framework skills. As of all permanent IT job vacancies advertised in the UK. Number of salaries quoted. Median salary change year-on-year.90 offered a salary of more than.10 offered a salary of more than. UK excluding London median salary. CPAN Job Vacancy Trend. The job posting trend of jobs advertised citing CPAN as a proportion of all permanent or contract IT jobs with a match in the Libraries, Frameworks Software Standards category. CPAN Salary Trend. This chart provides the 3-month moving average for salaries quoted in permanent IT jobs citing CPAN. CPAN Salary Histogram. The salary distribution of IT jobs citing CPAN over the 3 months to 14 March 2017.CPAN Top 4 Job Locations. The table below looks at the demand and provides a guide to the median salaries quoted in IT jobs citing CPAN within the UK over the 3 months to 14 March 2017 The Rank Change column provides an indication of the change in demand within each location based on the same 3 month period last year. Rank Change on Same Period Last Year. Matching Permanent IT Job Ads. Median Salary Last 3 Months. The belief that a change will be easy to do correctly makes it less likely that the change will be done correctly. An XP programmer writes a unit test to clarify his intentions before he makes a change We call this test-driven design TDD or test-first programming because an API s design and implementation are guided by its test cases The programmer writes the test the way he wants the API to work, and he implements the API to fulfill the expectations set out by the test. Test-driven design helps us invent testable and usable interfaces In many ways, testability and usability are one in the same If you can t write a test for an API, it ll probably be difficult to use, and vice-versa Test-driven design gives feedback on usability before time is wasted on the implementation of an awkward API As a bonus, the test documents how the API works, by example. All of the above are good things, and few would argue with them One obvious concern is that test-driven design might slow down development It does take time to write tests, but by writing the tests first, you gain insight into the implementation, which speeds development Debugging the implementation is faster, too, thanks to immediate and reproducible feedback that only an automated test can provide. Perhaps the greatest time savings from unit testing comes a few months or years after you write the test, when you need to extend the API The unit test not only provides you with reliable documentation for how the API works, but it also validates the assumptions that went into the design of the API You can be fairly sure a change didn t break anything if the change passes all the unit tests written before it Changes that fiddle with fundamental API assumptions cause the costliest defects to debug A comprehensive unit test suite is probably the most effective defense against such unwanted changes. This chapter introduces test-driven design through the implementation of an exponential moving average EMA , a simple but useful mathematical function This chapter also explains how to use the CPAN modules Test More and Test Exception. A unit test validat es the programmer s view of the application This is quite different from an acceptance test, which is written from the customer s perspective and tests end-user functionality, usually through the same interface that an ordinary user uses In constrast, a unit test exercises an API, formally known as a unit Usually, we test an entire Perl package with a single unit test. Perl has a strong tradition of unit testing, and virtually every CPAN module comes with one or more unit tests There are also many test frameworks available from CPAN This and subsequent chapters use Test More a popular and well documented test module 2 I also use Test Exception to test deviance cases that result in calls to die 3.Test First, By Intention. Test-driven design takes unit testing to the extreme Before you write the code, you write a unit test For example, here s the first test case for the EMA exponential moving average module. This is the minimal Test More test You tell Test More how many tests to expect, and you import the module with useok as the first test case The BEGIN ensures the module s prototypes and functions are available during compilation of the rest of the unit test. The next step is to run this test to make sure that it fails. At this stage, you might be thinking, Duh Of course, it fails Test-driven design does involve lots of duhs in the beginning The baby steps are important, because they help to put you in the mindset of writing a small test followed by just enough code to satisfy the test. If you have maintenance programming experience, you may already be familiar with this procedure Maintenance programmers know they need a test to be sure that their change fixes what they think is broken They write the test and run it before fixing anything to make sure they understand a failure and that their fix works Test-driven design takes this practice to the extreme by clarifying your understanding of all changes before you make them. Now that we have clarified the need for a module called EMA duh , we implement it. And, duh, the test passes. Yeeha Time to celebrate with a double cappuccino so we don t fall asleep. That s all there is to the test-driven design loop write a test, see it fail, satisfy the test, and watch it pass For brevity, the rest of the examples leave out the test execution steps and the concomitant duhs and yeehas However, it s important to remember to include these simple steps when test-first programming If you don t remember, your programming partner probably will 4.Exponential Moving Average. Our hypothetical customer for this example would like to maintain a running average of closing stock prices for her website An EMA is commonly used for this purpose, because it is an efficient way to compute a running average You can see why if you look at the basic computation for an EMA. today s price x weight yesterday s average x 1 - weight. This algorithm produces a weighted average that favors recent history The effect of a price on the average decays exponentially over time It s a simple function that only needs to maintain two values yesterday s average and the weight Most other types of moving averages, require more data storage and more complex computations. The weight, commonly called alpha is computed in terms of uniform time periods days, in this example.2 number of days 1.For efficiency, alpha is usually computed once, and stored along with the current value of the average I chose to use an object to hold these data and a single method to compute the average. Test Things That Might Break. Since the first cut design calls for a stateful object, we need to instantiate it to use it The next case tests object creation. I sometimes forget to return the instance self so the test calls ok to check that new returns some non-zero value This case tests what I think might break An alternative, more extensive test is. This case checks that new returns a blessed reference of class EMA To me, this test is unnecessarily complex If new returns s omething, it s probably an instance It s reasonable to rely on the simpler case on that basis alone Additionally, there will be other test cases that will use the instance, and those tests will fail if new doesn t return an instance of class EMA. This point is subtle but important, because the size of a unit test suite matters The larger and slower the suite, the less useful it will be A slow unit test suite means programmers will hesitate before running all the tests, and there will be more checkins which break unit and or acceptance tests Remember, programmers are lazy and impatient, and they don t like being held back by their programming environment When you test only what might break, your unit test suite will remain a lightweight and effective development tool. Please note that if you and your partner are new to test-driven design, it s probably better to err on the side of caution and to test too much With experience, you ll learn which tests are redundant and which are especially helpful There are no magic formulas here Testing is an art that takes time to master. Satisfy The Test, Don t Trick It. Returning to our example, the implementation of new that satisfies this case is. This is the minimal code which satisfies the above test length doesn t need to be stored, and we don t need to compute alpha We ll get to them when we need to. But wait, you say, wouldn t the following code satisfy the test, too. Yes, you can trick any test However, it s nice to treat programmers like grown-ups even though we don t always act that way No one is going to watch over your shoulder to make sure you aren t cheating your own test The first implementation of new is the right amount of code, and the test is sufficient to help guide that implementation The design calls for an object to hold state, and an object creation is what needed to be coded. Test Base Cases First. What we ve tested thus far are the base cases that is, tests that validate the basic assumptions of the API When we te st basic assumptions first, we work our way towards the full complexity of the complete implementation, and it also makes the test more readable Test-first design works best when the implementation grows along with the test cases. There are two base cases for the compute function The first base case is that the initial value of the average is just the number itself There s also the case of inputting a value equal to the average, which should leave the average unchanged These cases are coded as follows. The is function from Test More lets us compare scalar values Note the change to the instantiation test case that allows us to use the instance ema for subsequent cases Reusing results of previous tests shortens the test, and makes it easier to understand. The implementation that satisfies these cases is. The initialization of alpha was added to new because compute needs the value new initializes the state of the object, and compute implements the EMA algorithm self - is initially undef so tha t case can be detected. Even though the implementation looks finished, we aren t done testing The above code might be defective Both compute test cases use the same value, and the test would pass even if, for example, self - and value were accidentally switched We also need to test that the average changes when given different values The test as it stands is too static, and it doesn t serve as a good example of how an EMA works. Choose Self-Evident Data. In a test-driven environment, programmers use the tests to learn how the API works You may hear that XPers don t like documentation That s not quite true What we prefer is self-validating documentation in the form of tests We take care to write tests that are readable and demonstrate how to use the API. One way to create readable tests is to pick good test data However, we have a little bootstrapping problem To pick good test data, we need valid values from the results of an EMA computation, but we need an EMA implementation to give us thos e values One solution is to calculate the EMA values by hand Or, we could use another EMA implementation to come up with the values While either of these choices would work, a programmer reading the test cases would have to trust them or to recompute them to verify they are correct Not to mention that we d have to get the precision exactly right for our target platform. Use The Algorithm, Luke. A better alternative is to work backwards through the algorithm to figure out some self-evident test data 5 To accomplish this, we treat the EMA algorithm as two equations by fixing some values Our goal is to have integer values for the results so we avoid floating point precision issues In addition, integer values make it easier for the programmer to follow what is going on. When we look at the equations, we see alpha is the most constrained value. today s average today s price x alpha yesterday s average x 1 - alpha. alpha 2 length 1.Therefore it makes sense to try and figure out a value of alpha t hat can produce integer results given integer prices. Starting with length 1, the values of alpha decrease as follows 1, 2 3, 1 2, 2 5, 1 3, 2 7, and 1 4 The values 1, 1 2, and 2 5 are good candidates, because they can be represented exactly in binary floating point 1 is a degenerate case, the average of a single value is always itself 1 2 is not ideal, because alpha and 1 - alpha are identical, which creates a symmetry in the first equation. today s average today s price x 0 5 yesterday s average x 0 5.We want asymmetric weights so that defects, such as swapping today s price and yesterday s average, will be detected A length of 4 yields an alpha of 2 5 0 4 , and makes the equation asymmetric. today s average today s price x 0 4 yesterday s average x 0 6.With alpha fixed at 0 4, we can pick prices that make today s average an integer Specifically, multiples of 5 work nicely I like prices to go up, so I chose 10 for today s price and 5 for yesterday s average the initial price This makes today s average equal to 7, and our test becomes. Again, I revised the base cases to keep the test short Any value in the base cases will work so we might as well save testing time through reuse. Our test and implementation are essentially complete All paths through the code are tested, and EMA could be used in production if it is used properly That is, EMA is complete if all we care about is conformant behavior The implementation currently ignores what happens when new is given an invalid value for length. Although EMA is a small part of the application, it can have a great impact on quality For example, if new is passed a length of -1, Perl throws a divide-by-zero exception when alpha is computed For other invalid values for length such as -2, new silently accepts the errant value, and compute faithfully produces non-sensical values negative averages for positive prices We can t simply ignore these cases We need to make a decision about what to do when length is invalid. One approach wou ld be to assume garbage-in garbage-out If a caller supplies -2 for length it s the caller s problem Yet this isn t what Perl s divide function does, and it isn t what happens, say, when you try to de-reference a scalar which is not a reference The Perl interpreter calls die and I ve already mentioned in the Coding Style chapter that I prefer failing fast rather than waiting until the program can do some real damage In our example, the customer s web site would display an invalid moving average, and one her customers might make an incorrect investment decision based on this information That would be bad It is better for the web site to return a server error page than to display misleading and incorrect information. Nobody likes program crashes or server errors Yet calling die is an efficient way to communicate semantic limits couplings within the application The UI programmer, in our example, may not know that an EMA s length must be a positive integer He ll find out when the application dies He can then change the design of his code and the EMA class to make this limit visible to the end user Fail fast is an important feedback mechanism If we encounter an unexpected die it tells us the application design needs to be improved. Deviance Testing. In order to test for an API that fails fast, we need to be able to catch calls to die and then call ok to validate the call did indeed end in an exception The function diesok in the module Test Exception does this for us. Since this is our last group of test cases in this chapter, here s the entire unit test with the changeds for the new deviance cases highlighted. There are now 9 cases in the unit test The first deviance case validates that length can t be negative We already know -1 will die with a divide-by-zero exception so -2 is a better choice The zero case checks the boundary condition The first valid length is 1 Lengths must be integers, and 2 5 or any other floating point number is not allowed length has no explicit upper limit Perl automatically converts integers to floating point numbers if they are too large The test already checks that floating point numbers are not allowed so no explicit upper limit check is required. The implementation that satisfies this test follows. The only change is the addition of a call to die with an unless clause This simple fail fast clause doesn t complicate the code or slow down the API, and yet it prevents subtle errors by converting an assumption into an assertion. Only Test The New API. One of the most difficult parts of testing is to know when to stop Once you have been test-infected, you may want to keep on adding cases to be sure that the API is perfect For example, a interesting test case would be to pass a NaN Not a Number to compute but that s not a test of EMA The floating point implementation of Perl behaves in a particular way with respect to NaNs 6 and Bivio Math EMA will conform to that behavior Testing that NaNs are handled properly is a job for the Perl int erpreter s test suite. Every API relies on a tremendous amount of existing code There isn t enough time to test all the existing APIs and your new API as well Just as an API should separate concerns so must a test When testing a new API, your concern should be that API and no others. Solid Foundation. In XP, we do the simplest thing that could possibly work so we can deliver business value as quickly as possible Even as we write the test and implementation, we re sure the code will change When we encounter a new customer requirement, we refactor the code, if need be, to facilitate the additional function This iterative process is called continuous design which is the subject of the next chapter It s like renovating your house whenever your needs change 7.A system or house needs a solid foundation in order to support continuous renovation Unit tests are the foundation of an XP project When designing continuously, we make sure the house doesn t fall down by running unit tests to validate al l the assumptions about an implementation We also grow the foundation before adding new functions Our test suite gives us the confidence to embrace change. Quality Software Management Vol 1 Systems Thinking Gerald Weinberg, Dorset House, 1991, p 236.Part of the Test-Simple distribution, available at I used version 0 47 for this book. Just a friendly reminder to program in pairs, especially when trying something new. Thanks to Ion Yadigaroglu for teaching me this technique. In some implementations, use of NaNs will cause a run-time error In others, they will cause all subsequent results to be a NaN. Don t let the thought of continuous house renovation scare you off Programmers are much quieter and less messy than construction workers.

Comments

Popular Posts