Objektno orjentirano programiranje Predavanje 9 Postojani objekti, serijalizacija, marshaling, relacijske baze podataka
Postojani objekti - osnove eng. persistent objects Bez obzira na veličinu poslovne aplikacije, ona će gotovo uvijek koristiti baze podataka Podaci su temelj programa Kada se objekt instancira u aplikaciji on živi maksimalno koliko i aplikacija Da bi objekt nastavio živjeti i nakon što aplikacija završi mora biti zapisan u neku vrstu sustava pohrane Stanje objekta je definirano vrijednošću njegovih atrbuta
Postojani objekti - osnove Koncept spremanja stanja objekta na način da se može kasnije ponovno koristiti zove se postojanost (eng. persistence) Pojam postojani objekt (eng. persitstent object) označava objekt čije se stanje može povratiti i koristiti neovisno o samo jednoj aplikaciji Aplikacija 1 Aplikacija 2 Zapiši objekt Učitaj objekt Sustav pohrane
Postojani objekti - osnove Postoje različiti načini spremanja stanja objekta, neki od njih su: Spremanje u file Spremanje u relacijsku bazu podataka Spremanje u objektnu bazu podataka Najjednostavniji način je spremanje u datoteku, što nije standard kod poslovnih aplikacija
Spremanje objekta u datoteku Zapisivanje objekta u datoteku je različito od zapisivanja vrijednosti neke varijable u datoteku Spremanje varijabli u npr. tekstualnu datoteku (vrijednosti odvojene delimiterom) Objekt nije samo kolekcija primitivnih tipova, može sadržavati i druge objekte Da bi smo spremili objekt moramo ga razbiti u manje dijelove koje onda možemo zapisati u datoteku Moramo znati na koji način objekt ponovno vratiti u izvorni oblik
Serijalizacija Da bi objekt slali kroz kanal (npr. putem interneta) potrebno ga je dekonstruirati (razbiti u elementarne podatke, npr. byte stream), poslati i onda ga ponovno složiti na drugom kraju kanala ovaj proces naziva se serijalizacija (eng. serialization) Proces samog slanja kroz mrežu zove se marshaling Serijalizirani objekt se može zapisati u file i poslije opet vratiti u originalno stanje Serijaliziacija i deserijalizacjia trebaju koristiti iste specifikacije (metodu dekompozicije i kasnije vraćanja u stanje objekta) slično kao enkripcijski algoritam Java pruža interfejs Serializable.NET jezici pružaju interfejs ISerializable
Spremanje objekta u datoteku Moderni jezici imaju ugrađene mehanizme za postojanost objekata Kao i većina jezika Java koristi koncept toka za I/O Da bi spremili objekt u datoteku Java koristi Stream Da bi pisali u Stream objekt mora implementirati interfejs Serializable ili Externaizable Ograničenje ovakvog pristupa je da se za povraćanje objekta treba koristiti isti mehanizam/tehnolgija (Java) Java mora biti na obje strane ovog procesa
Serijalizacija u Javi package Serialization; import java.util.*; import java.io.*; class Osoba implements Serializable{ private String ime; public Osoba(){ } public Osoba(String i){ System.out.println( Konstruktor ); ime = i; } String dohvatiime() { return ime; } }
public class SpremiOsobu implements Serializable{ public SpremiOsobu(){ Osoba osoba = new Osoba( Ivo Ivić ); try{ FileOutputStream fos = new FileOutputStream( Dat.txt ); ObjectOutputStream oos = new ObjectOutputStream(fos); oos.writeobject(osoba); oos.flush(); oos.close(); } catch(exception e){ e.printstacktrace(); } }}
Serijalizacija u Javi U ovom primjeru: Instancira se objekt Osoba Objekt se serijalizira Objekt se sprema u datoteku Dat.txt Objekt se jednostavno serijalizira sa: oos.writeobject(osoba);
Serijalizacija putem interfejsa Primjer razlike između interfejsa i implementacije (znamo kako koristiti serijalizaciju ali ne znamo detalje implementacije) Primjer vraćanja objekta iz datoteke package Serialization; import java.io.*; import java.util.*; public class UcitajOsobu{ public UcitajOsobu(){ try{ FileInputStream fis = new FileInputStream( Dat.txt ); ObjectInputStream ois = new ObjectInputStream(fis); Osoba osoba = (Osoba )ois.readobject(); System.out.print( Učitano ime osobe: ); System.out.println(osoba.dohvatiIme()); ois.close(); } catch(exception e){ e.printstacktrace(); } } }
Što se događa s metodama pri serijalizaciji? Objekti se po definiciji sastoje od atributa i metoda Atributi se serijaliziraju, ali što je s metodama? U primjeru Jave metode se ne serijaliziraju Pri ovakvoj serijalizaciji Java treba biti na obje strane procesa (serijalizacija i deserijalizacija) Ako jedna aplikacija serijalizira, druga aplikacija koja radi deserijalizaciju treba imati istu definiciju klase Ipak, što se tiče programera nema konceptualne razlike (iako fizička implementacija ne odgovara točno konceptualnom modelu)
Korištenje XML-a u procesu serijalizacije Vidjeli smo primjer serijalizacije na jednoj platformi XML nam omogućuju serijalizaciju/deserijalizaciju kroz različite platforme Generira se XML file koji predstavlja atribute klase Osoba Da bi u C# omogućili ovu funkcionalnost potrebne su dodatne definicije u klasi [XmlRoot( osoba )] public class Osoba... [XmlAttribute( ime )] public String Ime... [XmlElement( god_starosti )] public int God_starosti
Korištenje XML-a u procesu serijalizacije Getteri i setteri su standardizirani Korisno jer ne mora svaki programer smišljati svoja imena za ove metode [XmlAttribute( ime )] public String Ime { get { return this.strime; } set { if (value == null) return; this.strime = value; } }
Korištenje XML-a u procesu serijalizacije Prilikom postavljanja vrijednosti atributa ne trebamo eksplicitno pozivati setter već možemo koristiti jednostavno pridruživanje vrijednosti this.ime = ime; Kada se ova naredba izvrši automatski se poziva setter Slično kao preopterećenje operatora u C++
Korištenje XML-a u procesu serijalizacije public void Serialize() { Osoba[] ljudi = new Osoba[3]; ljudi[0] = new Osoba ( Ivo Ivić, 32, 95); ljudi[1] = new Osoba ( Mate Matić, 35, 67); ljudi[2] = new Osoba ( Jure Jurić, 65, 77); XmlSerializer serializator= new XmlSerializer(typeof(Osoba[])); TextWriter writer= new StreamWriter( osoba.xml ); serializator.serialize(writer, ljudi); writer.close(); }
<?xml version= 1.0 encoding= utf-8?> <ArrayOfOsoba xmlns:xsi= http://www.w3.org/2001/xmlschema-instance xmlns:xsd= http://www.w3.org/2001/xmlschema > <Osoba ime= Ivo Ivić > <god_starosti>32</god_starosti> </Osoba> <Osoba ime= Mate Matić > <god_starosti>35</god_starosti> </Osoba> <Osoba ime= Jure Jurić > <god_starosti>65</god_starosti> </Osoba> </ArrayOfOsoba>
public void DeSerialize() { Osoba[] ucitaniljudi; XmlSerializer serializator = new XmlSerializer(typeof(Osoba[])); TextReader reader = new StreamReader( osoba.xml ); ucitaniljudi = (Osoba[])serializator.Deserialize(reader); Console.WriteLine( Ucitani ljudi su: ); foreach (Osoba osoba in ucitaniljudi) { Console WriteLine(osoba.Ime+ ima + osoba.god_starosti + godina. ); } }
Pisanje u relacijsku bazu podataka Relacijske baze podataka su jedan od najuspješnijih alata u IT industriji Relacijske baze i danas igraju važnu ulogu iako možda postoje i bolje tehnologije Velika većina poslovnih aplikacija koristi relacijske baze podataka (Oracle, SQLServer, MSAccess ) Iako se radi o korisnom alatu, može doći do problema kada se radi interakcija s objektima Objekt koji se potencijalno sastoji od drugih objekata želimo zapisati u relacijski model koji nije dizajniran na OO način
Relacijske baze podataka sastoje se od tablica
Pisanje u relacijsku bazu podataka Objektno orijentirani model se ne temelji na tablicama Budući da se objekti ne mapiraju jednostavno u tablice razvijene su objektno orijentirane baze podataka (90ih) Iako su ovakve baze bolje predstavljale OO model postoji jedan veliki problem: legacy data (podaci koji već duže vremena skladišteni u postojećem formatu) Većina tvrtki koriste relacijske baze podataka i većina ukupnih svjetskih podataka je spremljena u relacijskom modelu Dodatna stavka u korist relacijskih baza je da one provjereno funkcioniraju na različitim nivoima skaliranja
Pisanje u relacijsku bazu podataka Iako je objekte lakše zapisivati u objektno orijentirane baze podatka, cijena konverzije postojećih podatka iz relacijskog u objektni model je često previsoka OO baze se koriste uglavnom u samo novijim sustavima koji se ne povezuju na legacy podatke Želimo riješiti sljedeći problem: želimo pisati OO aplikacij i imati pristup legacy podacima u relacijskim bazama podataka Radi se o mapiranju iz objektnog u relacijski model
Pisanje u relacijsku bazu podataka Prilikom korištenja baza podataka postoji sljedeća struktura: 1. Klijent baze 2. Server baze 3. Baza podataka Korisnička aplikacija obično predstavlja klijenta koji podsredstvom servera obavlja interakciju s bazom podataka Klijent komunicira s bazom putem SQL izraza (Structured Query Language)
Pisanje u relacijsku bazu podataka SQL korisnik klijent baze server baze Baza driveri podataka Jedan od problema komunikacije sa specifičnom bazom je da su driveri baze vezani za proizvođača i koriste posebne protokole za komunikaciju
Pisanje u relacijsku bazu podataka Microsoft je razvio standard nazvan Open Database Connectivity (ODBC) koji apstrahira komunikaciju sa bazom Pisanjem klijenata po ODBC API-ju omogućavamo našim aplikacijama da se spajaju na više različitih servera baza podataka driver MSSQL klijent baze ODCB driver Oracle driver Access
Dio 2. Kvaliteta softvera Karakteristke kvalitete softvera postoje interne i eksterne karakteristike kvalitet softvera Eksterne karakteristike iz perspektive korisnika softvera: Ispravnost (eng. correctness) koliko je sustav bez pogreški u specifikaciji, dizajnu i implementaciji lakoća korištenja (eng. usability) Efikasnost (eng. efficiency) u vidu korištenja memorije i vremena izvršavanja Pouzdanost
Karakteristike kvalitete Zaštita od neovlaštenog pristupa- dijelovima programa ili podacima Prilagodljivost koliko se sustav može koristiti za namjene za koje nije prethodno dizajniran Preciznost odnosi se na kvantitativni ishod sustava Robusnost do kojeg stupnja sustav nastavlja ispravno raditi uz prisutnost neprihvatljivih unosa i stresnih uvjeta okoline Korisnici mare samo za eksterne značajke kvalitete softvera Programere zanimaju i interne značajke kvalitete softvera
Interne karakteristike kvalitete softvera Lakoća održavanja koliko lako možemo mijenjati ili dodavati svojstva, poboljšavati performanse ili ispravljati pogreške Fleksibilnost- Koliko lako možemo prenamijeniti sustav za namjenu različitu od one s kojom smo započeli Portabilnost- koliko lako možemo prilagoditi sustav da radi u drukčijem okruženju od onog za kojeg je inicijalno dizajniran Mogućnost ponovnog korištenja dijelova sustava za neki drugi sustav Čitljivost koliko lako se može čitati i razumjeti izvorni (eng. source) kod Mogućnost testiranja- koliko lako se mogu provoditi unit-testovi ili system-testovi
Interne karakteristike kvalitete softvera Interne i eksterne karakteristike se donekle preklapaju jer interne karakteristike utječu na eksterne Glavni princip kvalitete softvera je da poboljšanjem kvalitete reduciramo troškove razvoja Kvaliteta softvera rezultira manjim brojem grešaka Troškovi razvoja se povećavaju: promjenom zahtjeva, promjena u dizajnu ili posljedica potrebe za debugiranjem Uklanjanje pogrešaka je prema statistikama aktivnost koja uzima najviše vremena u procesu razvoja
Testiranje Testiranje je najpopularnija tehnika osiguravanja kvalitete softvera Neke vrste testiranja obavljaju developeri, a neke specijalizirane osobe Unit testing testiranje klasa ili malog dijela programa kojeg je napisao jedan developer, i testira se kao zasebna cjelina odvojena od sustava Component testing testiranje klasa, manjeg dijela programa ili programskog elementa kojeg je pisalo više developera, i testira se kao zasebna cjelina odvojena od sustava
Testiranje Integration testing kombinirano izvođenje više klasa, paketa, komponenti ili podsustava koje je razvilo više developera ili programerskih timova. Ovakav tip testiranja počinje čim postoji više klasa za testiranja i traje dok cijeli sustav nije završen Regression testing ponavljanje prethodno izvršenih testova u svrhu pronalaženja naknadno uvedenih bugova System testing izvođenje softvera u konačnoj konfiguraciji, uključujući integraciju s drugim softverskim i hardverskim sustavima
Testiranje Testovi koje obavlja specijalizirano osoblje: beta testiranje customer-acceptance tests performance tests configuration tests platform tests stress tests usability tests
Testiranje Testiranje se obično dijeli u dvije kategorije: black-box testing tester ne može vidjeti način unutrašnjeg funkcioniranja komponente/modula white-box testing tester ima uvid u unutrašnje funkcioniranje komponente/modula Razlika između testiranja i debugiranja Testiranje ne može dokazati da sustav nema pogrešaka, može samo pokazati da ima U radu na projektima developer testiranje bi u prosjeku trebalo uzeti 8-25% vremena
Testiranje Prilikom korištenja klasa najbolje ih je tretirati kao black-box Kada želimo testirati klase/module, najbolje ih je tretirati kao whitebox, na taj način možemo temeljitije testirati Svaka zasebna cjelina se treba posebno testirati prije integracije s ostalim komponentama Ako pišemo više funkcionalnosti treba ih prvo svaku zasebno testirati Testiranje po zahtjevima (eng. requirements) najbolje je testove napisati u fazi zahtjeva i prije nego smo napisali kod Dizajniranje testnih scenarija u fazi dizajna proizvoda ovo pomaže da se uoče pogreške u zahtjevima i dizajnu koje skuplje od grešaka pri kodiranju
Testiranje Developeri se često znaju pitati da li da prvo pišu testove pa kod ili obrnuto: Pisanje testova prije koda ne uzima više vremena nego što bi inače trebalo Ako testove napišemo prije ranije možemo pronaći i ispraviti pogreške Pisanje testova prije omogućava nam da prvo razmislimo zahtjevima i dizajnu prije pisanja koda što rezultira boljim kodom Bolje otkrivamo loše zahtjeve pišući testove
Testiranje podataka Vrste pogrešaka vezano za podatke: Premalo (ili ništa) podataka Previše podataka Kriva vrsta podataka Kriva veličina podataka Neinicijalizirani podaci
Testiranje klasa Napravimo jednu mock klasu koja služi za testiranje druge klase: poziva objekt sa zadanim skupom inputa koristi višestruke pozive sa različitim inputima dohvaća povratne vrijednosti loggiranje ponašanja klase Komercijalni alati: JUnit, CppUnit, NUnit Testiranje je jednostavnije ako imamo automatizirani input koji se uspoređuje s očekivanim povratnim vrijednostima pogotovo za regression test
Testiranje Random-data generatori testiraju za neobične kombinacije podataka Modularni dizaj je lakše testirati određeni dio koda možemo testirati bez user-iterface-a Testiranje bez mjerenja pokrivenosti koda obično koristi samo 50-60% koda Coverage monitor je alat koji služi za praćenje udjela koda u testiranju Na taj način znamo koji smo dio koda pokrili testovima, a koje nismo Re-testiranje nakon bilo kakvih promjena u kodu
Evidencija testiranja Potrebno je imati evidenciju testiranja da vidimo kako promjene utječu na sustav u pozitivnom ili negativnom smislu Neke stvari koje možemo evidentirati: Administrativni opis pogreške (datum, tko je prijavio, naziv, build number ) Opis problema Koraci potrebni za reproduciranje problema Preporuka o rješavanju problema Vezani problemi
Evidencija testiranja Ozbiljnost problema (fatal, cosmetic ) Izvor problema: zahtjevi, dizajn, kodiranje, testiranje Klase koje treba promijeniti za popravak problema Broj linija koda koje su obuhvaćene problemom Broj sati utrošen za pronalazak problema broj sati za popravak