SITNA CREVCA<>
082017<><>

Kako postati programer (11): šabloni, izuzeci, build alatke, testiranje...

Bez njih ne možemo

Dan (ne)zavisnosti, kako izbeći da program „pukne”...

Zamislite običnu funkciju koja vraća veći od dva parametra koja joj prosledite. U tipiziranim jezicima morate unapred zadati tip parametara funkcije. Da biste napravili kôd koji obavlja istu operaciju nad sva tri tipa promenljivih, kao u našem primeru, morali biste da napišete tri odvojene funkcije koje bi se razlikovale samo po tipu parametara. Zato postoje šabloni koji se u C++-u nazivaju Templates, u Javi i Swiftu Generics itd. Iako ste napisali samo jednu šablonsku funkciju, prilikom procesa kompajliranja, kompajler će zaista „ispod haube” napraviti tri funkcije. Napomena: poređenje char tipova se vrši po njihovoj ASCII vrednosti.

Ovde ćemo završiti sa šablonima (templates u Javascriptu su potpuno druga stvar). Njihova upotrebna vrednost je velika, a na njima se zasnivaju u našim tekstovima ranije pominjane kolekcije podataka. Primer je pisan u jeziku C++.

#include <iostream>

using namespace std;

template <typename T> T thatsWhatSheSaid(T br1, T br2) {

if (br1 > br2) return br1;

else return br2;

}

int main(int argc, char** argv) {

int x = 10, y = 20;

float a = 1.5, b = 1.6;

char c1 = ’a’, c2 = ’b’;

cout << thatsWhatSheSaid(x, y); //vraca 20

cout << thatsWhatSheSaid(a, b); //vraca 1.6

cout << thatsWhatSheSaid(c1, c2); //vraca ’b’

return 0;

}

Izuzeci (exceptions)

U prošlom broju smo pominjali kako možete reprodukovati Stack Overflow grešku koja dovodi do toga da vaš program „pukne”. Međutim, postoji još veliki broj izuzetaka na koje vas kompajler i IDE neće unapred upozoriti, a koje mogu dovesti do pucanja programa, na primer, ukoliko vaš program pokuša da pročita sadržaj nekog fajla na hard-disku koji ne postoji, ukoliko premašite indeks niza kom pristupate, ukoliko nastupi deljenje sa promenljivom koja je jednaka nuli i tako dalje. Tema o izuzecima je preobimna, pa ćemo se osvrnuti samo na neke detalje.

Često u vašem kôdu možete napisati uslove kako biste sprečili da dođe do pojave izuzetaka. Na primer, pre deljenja možete ručno napisati proveru da li je promenljiva jednaka nuli ili pre pristupa fajlu izvršiti proveru da li fajl postoji na disku. Loša strana ovog postupka je što će kôd postati previše natrpan proverama i biće teško pratiti šta je uopšte bila njegova osnovna namena. Zato je nekad bolje deo kôda ili poziv funkcije obaviti try-catch blokom.

Ukoliko na ovaj način ne uhvatite izuzetak, program će pući. Ako ga uhvatite, imate šansu da, u zavisnosti od izuzetka, probate da reagujete, „popravite” neke stvari u programu i nastavite sa njegovim izvršavanjem. Na primer, ako čitanje jednog fajla nije uspelo, a to nije kritično za rad programa, možete nastaviti sa čitanjem preostalih fajlova. U suprotnom, možete obavestiti korisnika o problemu i „na elegentan način” ugasiti aplikaciju.

Drugi slučaj je nastanak izuzetka u nekoj ugnježdenoj funkciji. Čak i ako ga tamo „uhvatite”, moguće je da je logiku za nastavak rada aplikacije zgodnije napisati u nekoj funkciji tri nivoa „iznad”. Dovoljno je da napišete try-catch blok na tom prethodnom nivou i izuzetak će se propagirati unazad kroz ceo stek (bubble up), sve dok ne naiđe na pozivnu funkciju sa proverom. Ako nigde ne uhvatite izuzetak sve do main funkcije, program će pući.

Postoji više tipova izuzetaka, zato je potrebno pogledati u dokumentaciji ili u kôdu koje izuzetke neka funkcija može „baciti” (često IDE može da automatski ponudi ove informacije). Pored ili umesto hvatanja konkretnog izuzetka, možete generički hvatati bilo koji.

public static void main(String args[]) {

int br1, br2;

try {

br1 = 0;

br2 = 50 / br1;

System.out.println(„Ovde kod nece stici”);

} catch (ArithmeticException e) {

// Blok koji hvata divide-by-zero error

System.out.println(„Error: Deljenje sa nulom”);

}

System.out.println(„Nastavak programa”);

}

Sami možete napraviti svoje izuzetke kao klasu koja nasleđuje baznu Exception klasu. Ako želite da vaša funkcija baci exception, potrebno je da joj prilikom definicije dodate naredbu throw, za kojom pišete tip izuzetka. Zašto biste uopšte pravili izuzetak? Zamislite da neko koristi vašu biblioteku i situaciju u kojoj ona može da izvrši neku nelegalnu operaciju. Vi nemate pojma kako bi korisnik vaše funkcije želeo da obradi takav slučaj, pa zato odgovornost za to prebacujete na njega preko izuzetka.

Jedna od tehnika je da se umesto exceptiona ipak koriste IF provere, pa ukoliko dođe do greške, poruku o njoj možete čuvati kao neki integer/enum/strukturu i slično (error code). Mana ove tehnike je što zauzima povratnu vrednost vaše funkcije, a uz to morate vraćati vrednost unazad kroz sve prethodne funkcije. Takođe, morate imati evidenciju značenja error kôdova, mada se svi ovi problemi mogu prevazići. Posebna priča je postojanje checked i unchecked izuzetaka u Javi. U praksi, postoji mnogo slučajeva od kojih zavisi kada i kako baratati izuzecima.

Build Tools, Dependency Managers

Na početku ovog serijala tekstova pominjali smo programe koji automatizuju sve korake potrebne da se vaš kôd kompajlira i pokrene na računaru.

Ako govorimo o Javi, najpopularniji alat koji olakšava menadžment projekta naziva se Maven. Možete ga posebno instalirati, mada ste podršku verovatno već dobili instaliranjem vašeg omiljenog IDE-a. Maven pre svega postavlja neke konvencije koje bi vaša aplikacija trebalo da prati, u smislu rasporeda foldera i fajlova, redosleda kompajliranja klasa i biblioteka i tako dalje, tako da se podešavanja Mavena tiču samo navođenja izuzetaka od ovih konvencija.

Uz to, Maven obezbeđuje da se sve biblioteke koje vaša aplikacija koristi čuvaju i automatski preuzimaju sa udaljenih servera (repozitorijuma) ukoliko nisu prisutne na nekom od računara koji se koriste za njen razvoj. To može biti javni Mavenov repozitorijum ili neki vaš privatni, ukoliko ga sami kreirate/zakupite. Pre preuzimanja ovih biblioteka (koje se nazivaju dependencies), Maven će proveriti da li ih je moguće pronaći u lokalu na vašem računaru (radi se o skrivenom „.m2” folderu koji se može naći na jednoj od nekoliko standardnih putanja na vašem disku). Umesto termina dependency ili library, podjednako se koristi i termin Maven artifact. Maven će se takođe postarati da sve biblioteke u lokalnom i udaljenom repozitorijumu budu osvežene novom verzijom ako ih sami razvijate kao lokalne programske projekte. Ovo „baratanje zavisnostima”, koje postaje znatno složenije kada biblioteke zavise od drugih biblioteka, čini da Maven bude i Dependency Manager.

Mavenu se podešavanja zadaju u fajlu XML formata pod nazivom POM. Alternativna programska rešenja su pre svega nešto stariji Ant, zatim Gradle, čija podešavanja nisu zasnovana na ponekad teško čitljivom XML formatu, Ivy i drugi.

Ako pogledamo JavaScript i front end razvoj, tu je zbog različitog programskog steka (tj. svih koraka i tehnologija u procesu od pisanja do korišćenja aplikacije) situacija znatno drugačija. Pomoćne aplikacije koje se danas koriste mogu se podeliti na više grupa, kao što su package/dependency menadžeri, bundleri i task runneri. Što je najgore, neki od ovih alata mogu da imaju i više od jedne uloge. Na ovaj džumbus pojmova u vezi front-end programiranja smo i ranije upozoravali i to je poznata stvar u front end svetu.

Najpoznatiji package manager je Npm (Node package manager). On olakšava ubacivanje biblioteka i frameworkova u vaš web projekat. Posle instaliranja Npm-a, dodavanje biblioteke u projekat se svodi na kucanje komande npm install ime_biblioteke. Kao što, recimo, Maven ima svoj „.pom” fajl, tako Npm ima fajl package.json u kojem se vodi evidencija o svim bibliotekama od kojih vaš projekat zavisi. Bower, drugi poznati menadžer paketa, je mrtav, a šta li se dešava sa novijim Yarnom?

Gulp i Grunt su task runneri. Oni mogu da posmatraju promene u vašem kôdu i automatski pokrenu neke procese prilikom naprednijeg front-end developmenta. Na primer, svaki put kada napravite izmene u SASS fajlu, Gulp može da pokrene prevođenje u CSS fajl. Isto važi za bilo koju drugu akciju, kao što je minifikacija kôda, pokretanje testova i tako dalje. Ove alatke možete zameniti tzv. Npm skriptama ili Webpackom.

Webpack je trenutni hit bundlera. Ako se vaša web aplikacija sastoji od mnogobrojnih fajlova i biblioteka, onda će pozivanje svakog od njih prilikom posete vašem sajtu zahtevati novu HTTP konekciju, duže trajanje celog procesa i tako dalje (govorimo o svim onim script tagovima u HTML fajlu koji učitavaju biblioteke). Bundler omogućava da se sve zavisnosti spakuju u manji broj fajlova. Takođe, veličina biblioteka se optimizuje izbacivanjem nepotrebnih karaktera kao što su razmaci, imena promenljivih se skraćuju, a kôd postaje praktično nečitljiv za čoveka (što je, zapravo, ranije pomenuta minifikacija). Do sada nismo pominjali pravljenje modula u Javascript programima, ali znajte da bundleri pomažu i prilikom učitavanja biblioteka podeljenih po nestandardnim modulima, bez čega browser ne bi mogao da ih učita. On podržava i relativno nove JavaScript nativne ES6 module (podrška za njih u modernim browserima je tek skoro stigla). Webpack ume sam da zaključi kako da optimizuje slike ili CSS fajlove. Webpack takođe omogućava i nešto što se zove „code splitting”, tj. cepanje bundlea na celine. Ukoliko se deo vašeg kôda poziva samo u nekim, retkim slučajevima, ima smisla da se bundle podeli na više delova. Na kraju, Webpack Dev Server se koristi samo tokom faze programiranja, uz pomoć kojeg se izmene u kôdu mogu istog trenutka videti u web aplikaciji, bez potrebe za rekompajliranjem i refreshovanjem browsera (u praksi nije tako lako podesiti). Od ostalih bundlera popularan je Browserify.

Za razliku od JavaScripta i front end developmenta, koje nismo u potpunosti pokrili ovim izlaganjem, ostali programski jezici su jednostavniji što se tiče alatki za rukovanje build procesom. Maven može da se koristi i za druge jezike pored Jave, programiranje za Apple se od dependency menadžera oslanja na CocoaPods ili možda Carthage, a nedavno je predstavljen nativni package manager; za PHP je popularno koristiti Composer itd.

Unit Tests

Postoji više načina za testiranje aplikacije koju pravite. Svrha Unit testova je da testiraju pojedinačne delove kôda (units), najčešće funkcije. Zato, za razliku od drugih vrsta testova, ove pišu baš programeri.

Svi programski jezici imaju frameworkove za testiranje, i najverovatnije ćete sa IDE-om već dobiti alate koji su vam za to potrebni. Rezultat testa je obično predstavljen kao zeleno „svetlo” u IDE-u koje označava da se test uspešno završio.

Pisanje testa se svodi na pisanje test funkcije. Uz to, potrebno je da unapred pripremite ulazne vrednosti za koje znate očekivane rezultate.

Zapamtite naredbu assert, koja služi za utvrđivanje tačnosti očekivanih podataka. Ovako bi izgledala funkcija sabiranja dva broja, i njen unit test.

//funkcija

int saberiBrojeve(int a, int b) {

return a+b;

}

//test funkcija u drugom fajlu

void testSaberiBrojeve() {

Assert.IsEqual(saberiBrojeve(5, 10), 15);

Assert.IsEqual(saberiBrojeve(1000, -100), 900);

}

U praksi, pravljenje unit testa u Javi iz NetBeansa radi se klikom desnim tasterom na neku klasu, zatim Tools->Create/Update Tests. Videćete u stablu programa novi fajl. IDE omogućava da se test fajl već popuni šablonskim kôdom, u našem primeru funkcijama iz klase main. Na vama ostaje samo da pripremite očekivane vrednosti ulaznih i izlaznih podataka (mock data). Na slici možete videti test za našu funkciju koji je uspešan i za funkciju main koji nije prošao.

Testovi su izolovani od glavnog programa i relativno brzo se izvršavaju. Zamislite da funkcija koju testirate dobija podatke iz baze. Ukoliko dođe do greške u komunikaciji sa bazom, vaša funkcija može da dobije neispravne podatke, zbog čega će ona nepravedno pasti na testu. Upravo zbog toga je potrebno pripremiti nezavisne (mock) podatke, a uz to nije ni potrebno da bude pokrenut server na kome je baza.

Iz NetBeansa se testovi pokreću npr. desnim klikom na test fajl i biranjem opcije test (a ne run). Testovi su automatizovani način da utvrdite da li je došlo do neočekivanih rezultata u vašoj aplikaciji, što je naročito korisno ako ste u međuvremenu dodavali ili menjali kôd.

Mnogi programeri i timovi zanemaruju važnost testova, imaju svoje mišljenje za i protiv istih. Pošto pisanje i održavanje testova zahteva određen utrošak radnih sati, neke firme smatraju da je važnije da se to vreme iskoristi na razvijanje aplikacije. Iznad unit testova su integration testovi koji uključuju testiranje međusobno povezanih delova kôda, acceptance testovi za testiranje rada celokupne aplikacije koje će obaviti klijenti ili korisnici i tako dalje, jer postoji više različitih podela.

Test Driven Development (TDD) je način programiranja u kom prvo pišete test za funkciju, a tek onda i samu funkciju. Testiranje kao deo kreiranja aplikacije će verovatno uticati i na sam način organizovanja vašeg kôda, jer nije svaki kôd pogodan za test. Pomenućemo još i termin Behavior Driven Development (BDD) testiranja. Radi se o pojmu vrlo sličnom TDD-u. Prebacivanje iz TDD u BDD se može postići „jednostavnim” preimenovanjem naziva test-funkcija, ali se mogu koristiti specijalizovani frameworkovi. Radi se o testovima čije naredbe zvuče kao sastavljanje rečenica na engleskom jeziku. Tako implementirane testove mogu čitati i lica koja nisu upoznata sa kôdom aplikacije. Za Java unit testove ćete najčešće koristiti JUnit, za JavaScipt Jasmine ili Mocha, mada ima i drugih rešenja.

Ukoliko želite da testirate front end web aplikacije, postoji poseban način za testiranje korisničkog interfejsa. Selenium je jedan od najpoznatijih alata koji se integriše sa web browserom (Selenium 2, tj. Selenium Web Driver). U vašem programskom jeziku preko Seleniuma dobijate pristup DOM elementima na stranici, a testove pišete tako što preko kôda oponašate akcije korisnika koji je pristupio vašoj stranici. Prethodne verzije Seleniuma su se zvale Selenium IDE (mogli ste da snimate akcije u browseru poput video-rekordera i zatim da ih reprodukujete) i Selenium RC (Remote Control), koji je približniji Seleniumu 2, ali su oba rešenja sada zastarela.

The End of This Chapter

Sve vreme svog trajanja, ovaj serijal je bio pri vrhu čitanosti, makar sudeći po glasovima čitalaca koji učestvuju u našoj SMS nagradnoj anketi. Došlo je vreme da se oprostimo, uz nadu da su tekstovi bili od koristi delu čitalaca koji se zanimao za ove teme. Razmislićemo da li je izvodljivo da se jedna programerska rubrika održi u „Svetu kompjutera”, ali ne u obliku ovakvog kilometarskog serijala, već tako što bismo teme podelili među novim, „svežim” autorima, specijalizovanim za neke od oblasti koje smo pominjali.

Sve što smo naveli u prethodnih godinu dana i dalje stoji, iako je polje programiranja podložno brzim promenama. Od novih igrača pomenuli bismo programski jezik Kotlin, koji pretenduje da bude naslednik Jave, makar za Android programiranje. Još jedan buzzword koji pokušava da dobije na značaju su PWA (Progressive Web Applications), tj. web aplikacije koje će na mobilnim uređajima omogućiti iste funkcije i osećaj kao da koristite nativnu aplikaciju.

Svakako ima mnogo tema koje smo želeli da obradimo, ali nismo stigli, kao na primer način na koji ćete vaš back end kôd staviti u produkciju, podesiti server, postaviti ga na neki hosting i sve to povezati sa mobilnom, desktop i web aplikacijom, bazom itd. (LAMP/WAMP/MAMP, mean stack i sl.). Trebalo bi da vidite šta su to null vrednosti ili recimo enum vrsta promenljivih, REST pozivi, Q&A pozicije u softverskoj firmi, itd. Zatim, trebalo bi da obratite pažnju na pojmove dependency injection, inversion of control, scrum ili agile i druge metodologije rada u firmi, devops, itd. Sve pojmove sa kojima ste se do sada upoznali kroz serijal pogledajte detaljnije u vašem jeziku po izboru. Zatim, tu je i razvijanje mobilnih aplikacija.

No, ako ste do sada čitali naše tekstove, već ste otplivali daleko od obale na kojoj se sunčaju programeri početnici, noge vam više ne dotiču dno, ali se bez problema održavate na površini.

Ognjen POPOVIĆ

 
 NOVE TEHNOLOGIJE
HDR (Hygh Dynamic Range) TV uređaji
DeepStack pobeđuje u pokeru

 KOMPJUTERI I FILM
The Emoji Movie
The Nut Job 2
Filmovi, ukratko

 SITNA CREVCA
Fleš memorija i memorijske kartice
Kako postati programer (11): šabloni, izuzeci, build alatke, testiranje...
Šta mislite o ovom tekstu?

 VREMENSKA MAŠINA
Kwangmyongsong i drugari

 PRST NA ČELO
Klonovi koji to ipak nisu
Home / Novi brojArhiva • Opšte temeInternetTest driveTest runPD kutakCeDetekaWWW vodič • Svet igara
Svet kompjutera Copyright © 1984-2018. Politika a.d. • RedakcijaKontaktSaradnjaOglasiPretplata • Help • English
SKWeb 3.22
Opšte teme
Internet
Test Drive
Test Run
PD kutak
CeDeteka
WWW vodič
Svet igara



Naslovna stranaPrethodni brojeviOpšte informacijeKontaktOglašavanjePomoćInfo in English

Svet kompjutera