- GKO, luennot 2.-3.4.2004
- Delphi
- Kirja: Delphi-pikakurssi (VL)
- Delphi vs. Visual Basic
- Melkein yhtä helppokäyttöinen kuin VB, mutta monipuolisempi
- Sovelluskehittäjä ei ole riippuvainen muilla kielillä tehdyistä komponenteista, kuten VB:ssä
- Delphillä voi tehdä myös omia komponentteja - vaikka Visual Basiciin (mahdollisuus ActiveX-komponenttien julkaisuun)
- Object Pascal on oliokieli Basic ei (lukuunottamatta mahdollisesti VB:n viimeisimpiä versioita)
- Kylixin myötä delphillä on mahdollista tehdä myös Linuxissa kääntyvää koodia, mikä tuntuu melko kaukaiselta ajatukselta VB:ssa :-)
- Käyttöliittymän esittely
- komponenttipaletti
- object inspector
- käyttöliittymäkoodi ja pascal-koodi erotettu toisistaan
- erittäin nopea käännös (varsinkin C++:aan verrattuna)
- object pascal -kielestä
- kehitetty borlandin turbo pascalista (DOS-ohjelmoijat muistanevat) =)
- eläinesimerkki
- hybridikieli C++:n tapaan: rakenteinen ohjelmointikieli laajennettuna oliopiirteillä
- olioista huolimatta monet asiat tehdään edelleen rakenteisesti: perusaliohjelmakirjastot ovat _funktio_, ei oliokirjastoja (vrt. java)
- rakenteiset tyypit laajasti käytössä: tietueet, luetellut tyypit, joukot
- Object Pascal vs. C++
- C++:aan verrattuna huomattavasti luettavampi (makuasia?) ja havainnollisempi syntaksi, joka tosin vaatii enemmän tilaa
- { == begin, } == end, = == :=, == == = jne
- aliluokkiin ei tarvitse kirjoittaa konstruktoria, jos muutoksia yliluokkaan verrattuna ei ole
- virtuaalifunktiot ja niiden syrjäyttäminen (override) merkittävä eksplisiittisesti koodiin (hyvä!)
- yliluokan metodeja kutsuttaessa avainsana inherited
- Object Pascal ei tue moniperintää, malleja (Templatet) eikä operaattorien kuormitusta
- moniperinnän voi osittain korvata rajapinnoilla ja koostamisella (tästä lisää myöhemmin)
- mallifunktioitakin voi 'matkia' yksinkertaisissa tilanteissa
- Metodiosoittimet C++:aa joustavammat ja huomattavasti helpommat käyttää
- Käytetään tapahtumavälityksessä
- Metodiosoitin ei välttämättä ota kantaa olion luokkaan, kuten C++:ssa
- Olioihin viitataan koodissa oletuksena viitteinä, C++:n 'automaattisia konkreettisia olioita' ei ole
- Perustyypit ja rakenteiset tyypit ovat konkreettisia (ei tarvita erillistä muistinvarausta- ja vapautusta)
- Kielessä mukana dynaamiset taulukot ja aidot merkkijonot
- C++:aa vahvempi tyypitys (esim. int ja boolean eivät ole sama asia!)
- oliot tapana nimetä T-etuliitteellä (Esim. TObject, TEdit, TLabel, TIniFile)
- T == "Type"
- painolastia Turbo Pascalista...
- huom. delphissä on nykyään funktioiden kuormitus (vrt. delphi-moniste))
- delphissä komponentti == TComponent-luokasta peritty olio
- sisältää ominaisuuksia (propertyt) ja tapahtumia
- komponentti voi olla visuaalinen (näkyy ruudulla, peritty TControl-luokasta) tai näkymätön (esim. tietokantayhteys)
- ominaisuudet ovat eräänlainen julkinen rajapinta tiettyihin attribuutteihin, osaa ominaisuuksista voidaan säätää suunnitteluaikana
- tapahtumat ovat käyttäjän (tai ohjelman) toimintoja, jotka aktivoivat tietyn kohdan ohjelmakoodissa (tapahtumakäsittelijän)
- komponentteja voidaan rekisteröidä osaksi delphin käyttöliittymää komponenttipalettiin
- fyysisesti komponentit sijaitsevat BPL-kirjastoissa, jotka ovat muunneltuja DLL:ia.
- C++ Builder ja Delphi (uusimmat versiot) voivat käyttää samoja BPL-kirjastoja
- Esimerkkiohjelma: autolaskuri
- graafisten käyttöliittymien "hello world"
- ohjelma sopii eri käyttöliittymäkirjastojen perusideoiden esittelyyn
- Lisämateriaalia: Borland Developer network ja Delphin dokumentaatio
- [ http://community.borland.com/delphi/0,1419,1,00.html ]
- Tapahtumat
- Metodiosoittimia!
- abstrahoivat Windowsin oman viestinvälitysmekanismin (tästä lisää WinAPI-luennolla)
- voidaan säätää object inspectorista tai (usein joustavampaa) suoraan ohjelmakoodissa
- tapahtumakäsittelijä voi sijaita missä osassa koodia tahansa, kunhan se on jossain oliossa
- käsittelijöiden sijoittelussa kannattaa noudattaa tervettä järkeä...
- usein käsittelijän sijoittaminen kohdelomakkeelle (delphin oletus) on hyvä ratkaisu
- jos komponentit ja käsittelijät sijaitsevat samalla lomakkeella, delphin viitelaskuri hoitaa olioiden tuhoamisen
- jos halutaan automatisoida suurta määrää tapahtumia, jotka esim. sijaitsevat eri lomakkeilla, voi harkita esim. omaa luokkaa tapahtumakäsittelyyn, jonne eri lomakkeiden tapahtumat ohjautuvat
- esim. javassa melko yleistä (javassa tapahtumakäsittelijät ovat usein omissa olioissaan, mutta periaate on sama)
- tällöin muistinhallinnan kanssa on oltava tarkkana
- jos tapahtumaluokan olio tuhotaan, siitä on lähetettävä ilmoitus kaikille, jotka sitä käyttävät (tämä pätee yleisesti myös olioarvoisille ominaisuuksille)
- ilmoitukset voi hoitaa TComponentit FreeNotification-metodilla (tästä lisää myöhemminkin)
- tapahtumia voi määritellä itsekin
- tällöin käytetään Pascalin tyyppimääritystä
- Mahdollistaa lähettäjäolion (Sender) käsittelyn ilman Typecasteja
- lisää luennolla 'Omat komponentit'
- Huom. ajettaessa tapahtumapohjaista ohjelmaa näyttää siltä, että tapahtumia kutsutaan 'itsestään'
- todellisuudessa tapahtumien pohjalla on edelleen periaatteessa switch/case/if-silmukka, joka käy jatkuvasti läpi mahdollisia tapahtumia
- siis: windows-ohjelma(kin) on syöte/käsittely/tuloste-muotoa oleva, pääohjelmasta ja aliohjemista muodostuva ohjelma
- pääohjelma ja kaikille ohjelmille yhteiset alustukset piilotettu käyttäjältä (sovelluskehys, Application Framework)
- sovelluskehittäjän ei yleensä (onneksi!) tarvitse välittää tästä ns. Windowsin viestisilmukasta
- tapahtumakutsut ovat tavallisia funktiokutsuja, jotka esim. kasvattavat kutsupinoa (ks. debug)
- VAROITUS: toisiaan kutsuvien tapahtumakäsittelijöiden avulla on yllättävän helppoa tehdä ikuinen silmukka...
- jos käsittelijöitä on PAKKO kutsua 'päällekkäin', kannattaa käyttää esim. laskuria tai muuta tilamuuttujaa, joka varmistaa, ettei ikuista silmukkaa pääse syntymään
- Autolaskuri jatkuu...
- Tietokannat
- Tietokantapalvelimia
- Kaupallisia: Oracle, MS SQL, ...
- Open Source -ohjelmistoja: MySQL, PostgreSQL, FirebirdSQL (entinen InterBase)
- MySQL laajasti käytössä erityisesti Web-sovelluksissa
- "Lelu"ohjelmia (desktop databases): MS Access, Paradox
- Huom. soveltuvat hyvin henk. koht käyttöön ja tietokantaohjelmoinnin testaukseen
- Ohjelmoinnin kannalta on melkein sama käytetäänkö palvelinta vai desktop-tietokantaa
- Yhteystyyppejä
- ODBC (Open DataBase Connectivity)
- Microsoftin kehittämä yleisrajapinta yhteyksiin kaikkiin tietokantapalvelimiin verkon yli.
- Käyttö vaatii palvelinkohtaisen ODBC-ajurin asennuksen kaikille asiakaskoneille.
- Sovellus kommunikoi palvelimen kanssa SQL-kielellä
- Sovellus ei ota kantaa palvelimeen, vaan ainoastaan ajurin nimeen
- Mahdollistaa palvelimen vaihdon "lennossa" (tietokannan sisältö täytyy tietysti siirtää erikseen, tähän käy esim. Borlandin DataPump)
- Käytännössä eri palvelimien SQL-murteiden erot voivat aiheuttaa muutoksia koodiin
- Turvallisinta käyttää Standardia SQL-koodia (SQL92 laajasti tuettu, uudemmissa palvelimissa SQL99)
- SQL-koodin tarkastamiseen ks. Mimer SQL Validator
- Ainoa täysin SQL-standardia noudattava palvelin Ocelot
- Muissa palvelimissa puutteita (esim. MySQL:n vanhemmat versiot eivät tue alikyselyitä) ja epästandardeja lisäyksiä (esim. AUTO_INCREMENT-kenttä, käyttäjähallinta)
- Erittäin laajalle levinnyt. Käytännössä jokainen tietokantapalvelin tarjoaa ODBC-ajurin.
- Java-pohjaisilla sovelluksilla vastaava rajapinta JDBC (Java DataBase Connectivity)
- JDBC-ajureilla voidaan ottaa yhteys ODBC-kantoihin JDBC-ODBC -sillan kautta
- ADO ja OleDB
- OleDB = Microsoftin kehittämä uudempi COM-pohjainen rajapinta tietokantayhteyksiin
- ODBC:n tapaan jokaiselle palvelimelle tarvitaan oma OleDB-ajuri
- OleDB-ajurit ovat erikoistuneempia kuin ODBC-ajurit, mikä mahdollistaa periaatteessa ODBC:tä nopeamman yhteyden
- ODBC:tä monipuolisempi tietokannan käsite: esim. sähköpostikokoelma voidaan tulkita OleDB-"tietokannaksi"
- Ei vielä yhtä levinnyt kuin ODBC, ajurit eivät yhtä luotettavia
- Esim. MySQL:n OleDB-ajuri ei toimi kunnolla (kokeiltu on...)
- Tällä hetkellä yleisin OleDB:n käyttötapa on yhteys ODBC-ajuriin OleDB:llä (hidasta, mutta ohjelmointi suoraa ODBC:n käyttöä helpompaa)
- ADO (ActiveX Data Objects) = Kokoelma COM-komponentteja OleDB-yhteyksien käsittelyyn
- Yksinkertaistaa huomattavasti OleDB:n ohjelmointia
- Käytössä Delphin ADO-komponenteissa
- Tietokantojen omat kehitysrajapinnat (APIt)
- Yleensä nopeampia kuin standardirajapinnat
- Tietokantapohjaisten rajapintojen käyttö vaatii sitoutumista tietyn valmistajan komponentteihin
- Jos tietokantapalvelinta täytyy vaihtaa, myös osa koodista menee tällöin uusiksi
- ODBC:stä, ADO:sta ja OleDB:stä lisätietoa Microsoftin sivuilla
- [ http://searchdatabase.techtarget.com/sDefinition/0,,sid13_gci213238,00.html ]
- Delphin tietokantakomponentit
- Esimerkkiohjelma: TietokantaForm
- Yleiskomponentit
- TDataSet
- Yhteinen yliluokka kaikille tietojoukoille!
- Sisältää perusmetodit taulun selaamiseen (first, next, prev ym), tietojen päivitykseen (edit, post, cancel) ja siirtoon muihin komponentteihin (FieldByName, yhteys käyttöliittymäkomponentteihin DataSourcen avulla)
- Abstrakti luokka. Erikoistietokantoja varten käyttäjä voi määritellä vaikka oman DataSet-aliluokkansa
- Kehittäjä voi määritellä manuaalisesti käyttöliittymäkomponenteissa näkyvien kenttien ominaisuuksia (Field-komponentit)
- Kun SQL-kysely tehdään, Queryn oletustoteutus luo kentät 'lennossa'
- Omia säätöjä kannattaa tehdä, jos käytetään esim. ruudustoa ja lookup-kenttiä
- TDataSource
- Yhteyskomponentti TDataSet-luokan ja käyttöliittymäkomponenttien välillä
- Mahdollistaa käyttöliittymän riippumattomuuden tietokantayhteyden tyypistä
- Käyttöliittymäkomponentit
- Ruudusto, Edit, Memo, ComboBox ym...
- Jos DataSet-komponetti näyttää vain yhden taulun tietoja kerrallaan, kenttiä voi editoida suoraan!
- Tietoja voi hakea editointia varten rajoitetusti myös toisesta taulusta (ns. lookup list, M-1 -suhde)
- 1-M -suhteiden näyttö (esim. henkilön puhelinnumerot) mahdollista määrittelemällä Master-Detail -suhde taulujen välille
- jopa M-M -suhteiden editointi mahdollista yhdistämällä Master-Detail tauluun Lookup-kenttä!
- Myös kuvat ja binääridata (BLOB) mahdollisia
- 'Data-aware'-komponentteja: kun käyttäjä alkaa editoida jotain kenttää, DataSet-olio siirtyy muokkaustilaan
- Kun käyttäjä on tehnyt muutoksensa, ne välittyvät suoraan DataSet-komponentin avulla tietokantaan
- Ei tarvita välttämällä SQL Update -lauseita (ainakaan, jos editoidaan yhtä tai kahta taulua kerrallaan)
- Monimutkaisissa lomakkeissa voidaan tarvita myös omia säätöjä (erityisesti syötteen tarkistukset). Mukautetut, useita tauluja sisältävät kyselyt hakutoimintoja tai raportteja varten on tietysti tehtävä SQL:lla.
- VAROITUS: Delphin arkkitehtuuri mahdollistaa erittäin monipuoliset tietokantayhteydet yleiskäyttöisillä tietokantakomponenteilla, mutta niiden toimivuus on aina testattava! Palvelimissa, Windowsissa, ajureissa JA Delphin komponenteissa saattaa olla bugeja, jolloin määrätty palvelin-ajuri-yhteys-käyttöliittymäyhdistelmä ei toimi oikein!
- Eri palvelimien SQL-murteissa eroja
- Tarkista erityisesti lookup-kenttien toimiminen! (ADO+ODBC+MySQL delphin vanhemmalla versiolla: epämääräisiä ongelmia lookup-kenttien tietojen päivityksessä!) :-(
- Käytännössä Microsoftin järjestelmät toimivat hyvin ADO:lla ja esim. Paradox ja muut borlandin omat ajurit BDE:llä
- dbExpress ja ADO:n OLEDB ovat vielä niin uusia tekniikoita, että ajureissa saattaa olla virheitä (ainakin MySQL)
- ODBC:tä pidetään hitaana, mutta toimii käytännössä hyvin lähes kaikilla tietokannoilla
- Jos data-aktiiviset komponentit eivät toimi oikein, suorat SQL-kyselyt ja päivitykset Query-komponentilla toimivat kyllä. Tällöin käyttöliittymän voi tehdä vaikka tavallisilla komponenteilla (työlästä, mutta toimii varmasti)
- BDE
- Natiiviajureita (esim. Paradox), ODBC...
- BDE-yhteyksiä hallitaan Borlandin BDE Administratorilla (löytyy esim. Delphin päävalikosta Database->Explore
- Tietokantayhteys TDataBase-komponentilla, yhteyden tyyppi määritellään BDE:n aliaksena, lisäparametreja (esim. hakemistotiedot) voidaan antaa myös TSession-komponentilla
- ADO
- OLEDB-natiiviajureita (esim. Access), myös ODBC-yhteys mahdollinen
- Tietokantayhteys TAdoConnection-komponentilla, parametrit määritellään ConnectionString-merkkijonon avulla (voidaan tehdä komponentin 'wizardilla' tai käsin).
- dbExpress
- Vain tietokantakohtaiset dbExpress-ajurit
- 1-suuntainen DataSet (vain first- ja next -operaatiot)
- Ruudustokomponenttia ei voi käyttää suoraan
- Soveltuu esim. web-sovelluksiin, joissa tietokannan tulosteen generoidaan joka tapauksessa erikseen => ei tarvita 'aktiivisia' tietokantakomponentteja
- Datajoukon saa paikallisesti 2-suuntaiseksi yhdistämällä se ClientDataSet-komponenttiin
- Nopea.
- Hajautettu tietokannan käsittely (ClientDataSet)
- Tietojoukko kopioidaan editoinnin ajaksi sovelluksen muistiin, tietokantaa ei editoida suoraan kuten muilla yhteystyypeillä
- Päivitykset voidaan tehdä keskitetysti kutsumalla TClientDataSetin metodia ApplyUpdates
- Mahdollistaa tietokannan 'offline'-editoinnin ('briefcase model')
- Yhteys tietokantaan Provider-komponenttien avulla. Tässä 'tietokanta' voi olla toinen samassa projektissa oleva DataSet tai XML-tietovirta
- Tietokantasovelluksen suunnittelusta
- Delphin 'database expert'-velhojen ja vastaavien avulla ei oikeasti saa tehtyä leluohjelmia kummempia sovelluksia
- Kaikkien lomakkeiden suunnittelu Delphin IDE:n avulla käsin on mahdollista, mutta suurissa sovelluksissa erittäin työlästä ja herkkää tietokannan rakenteen muutoksille
- Ihannetapauksessa (koodaajan kannalta) koko käyttöliittymä luotaisiin dynaamisesti SQL-kyselyjen perusteella
- Käytännössä kaikkea ei kuitenkaan voida luoda täysin dynaamisesti (käyttäjät vaativat sovitetun käyttöliittymän, 1-M ja M-M -suhteet vaativat erillistä käsittelyä)
- Sovellusta suunniteltaessa otettava huomioon mahdollinen tarve tietokannan rakenteen muutoksille
- Klassinen tapaus: 1-M -suhde muutettava M-M-suhteeksi
- Ratkaisuja
- Mahdollisimman vähän 'käsin kirjoitettua' SQL:aa. Tarvittavat SQL-lauseet keskitetään yhteen luokkaan tai luodaan dynaamisesti
- Joskus osa rutiinitoimenpiteistä kannattaa sijoittaan omaan DataSetista (tai Querysta) perittyyn luokkaan.
- Mahdollisiman vähän kytköksiä eri lomakkeiden välille
- Perinnän avulla voi säästää huomattavasti koodia, jos tietokannassa on yleistyssuhteita
- 'metaluokkien' käyttö: jos kannassa on runsaasti samaa rakennetta olevia, mutta merkitykseltään erilaisia tauluja, käyttöliittymät niille kannattaa luoda dynaamisesti saman luokan variaatioina.
- Tietokantakursseja:
- Tietokannat ja tiedonhallinta (ks. moniste)
- Esimerkkiohjelma: Kerhon jäsenrekisteri ADO-komponenteilla
- Kyselyt ja taulut keskitetysti DataModuulissa
- Master-Detail -suhteita ja lookup-kenttiä voi määritellä Diagrammina
- Toimii samalla tietokannan dokumentaationa
- Huom! Ei sisällä syötteen tarkistuksia eikä kunnollista raportointia eikä hakutoimintoa
- Malli sopii myös harkkatyön pohjaksi, jos aikomuksena tehdä tietokantasovellus
- Esimerkkiohjelma: puhlu
- ks. delphi-moniste, dynaamisesti luotavat datakontrollit
- 'dynaaminen' tietokantasovellus
- Käyttöliittymäkomponentit luodaan 'lennossa' kyselyn perusteella, bonuksena html-ulostulo ja xml-synkronointi
- Huom. myös XML-liitäntää käytetään ClientDataSetin kautta
- XML:aa tarvitaan lähinnä, jos tarkoituksena yhdistää kahden epäyhteensopivan järjestelmän tietoja
- Jos käsiteltävä tietokanta on laaja tai tietokannan rakenteeseen on odotettavissa muutoksia, tämä on hyvä tapa