Artikkelit
Qt-sovelluskehys
Sujuvaa sovelluskehitystä C++:lla
Qt on C++-ohjelmointikielellä toteutettu sovelluskehys, jonka avulla sovelluksia voidaan siirtää helposti useille eri alustoille. Tunnettuja Qt:ta käyttäviä työpöytäsovelluksia ovat mm. Skype ja Google Earth. Qt on käytössä myös monissa sulautetuissa järjestelmissä ja se toimii MeeGon pääasiallisena rajapintana sovellusohjelmoijalle.
Qt:n alkuperäinen kehittäjä ja omistaja oli norjalainen Trolltech. Nokia osti Trolltechin vuonna 2008 ja on jatkanut Qt:n kehittämistä siitä asti. Nokia on muuttanut Qt:n lisensointia sallivammaksi ja kehitysprosessia avoimemmaksi. Qt on saatavissa avoimella LGPL- tai kaupallisella lisenssillä.
Alunperin Qt toimi lähinnä työpöytäympäristöissä sekä joissakin sulautetuissa järjestelmissä. Nokian omistus on siirtänyt kehityksen painopistettä mobiilijärjestelmien suuntaan, mutta Qt tukee edelleen useita työpöytäympäristöjä. Kehyksen sisällyttäminen Nokian laitteisiin on laajentanut Qt:n asennuskantaa: Nokia ilmoittaa toimittaneensa markkinoille yli 100 miljoonaa laitetta, joille voi kehittää sovelluksia Qt:lla.
Nokia on julkaissut suunnitelmiaan seuraavasta Qt:n versiosta 5, joka keskittyy erityisesti kehittämään Qt Quick -nimistä käyttöliittymien ohjelmointitekniikkaa. Qt Quickista lisää edempänä artikkelissa.
Natiivikoodia ilman virtuaalikonetta
Toisin kuin monissa muissa moderneissa ohjelmointialustoissa, Qt-sovellusten pääasiallinen ajoympäristö ei perustu virtuaalikoneeseen. Qt-ohjelmat kirjoitetaan C++-ohjelmointikielellä ja käännetään suoraan laitteistolla ajettavaksi binäärikoodiksi. Poikkeuksen tekee käyttöliittymien tekemiseen tarkoitettu Qt Quick, johon sisältyy JavaScript-virtuaalikone.
C++:lla toteutettavilla ohjelmilla ei ole käytettävissään automaattista muistinhallintaa, vaan kehittäjä on itse vastuussa ohjelman muistin varauksesta ja vapautuksesta. Muistin käsittely on merkittävä osa hyvin suunnitellun ohjelman rakennetta, joten manuaalinen muistinhallinta vaatii huolellisuutta ja kokemusta. Objektihierarkiat sekä olioiden omistussuhteet on suunniteltava ottaen huomioon muistinhallinnan tuomat vaatimukset, jotta muistin käsittelyyn liittyvien ongelmien määrä saadaan minimoitua.
Qt-kirjasto pyrkii vähentämään ohjelmoijan taakkaa tarjoamalla apuja muistinhallintaan. Qt-oliot voidaan esimerkiksi järjestää hierarkiaksi, jossa minkä tahansa olion vapauttaminen vapauttaa automaattisesti sen alapuolella hierarkiassa olevat oliot. Useat Qt:n rajapintaluokat toteuttavat implicit sharing -idiomin, jonka avulla olioiden kopiointi on tehokasta. Varsinainen kopio tehdään vasta, kun jokin olio tekee muutoksen yhteiseen dataan (copy-on-write-semantiikka). Tämän ansiosta parametrit ja paluuarvot voidaan välittää arvo-olioina (value object) olioviitteiden (object reference) sijaan. Arvo-olioihin perustuva ohjelmointi on yksinkertaisempaa ja siten usein sujuvampaa kuin olioviitteisiin perustuva.
Qt yksinkertaistaa tapahtumapohjaista ohjelmointia
Qt:n malli sovellusten rakentamiseen perustuu tapahtumapohjaiseen ohjelmointiin. Ohjelman sisäisistä tapahtumista lähetetään signaaleja (signals), jotka esitellään luokkamäärittelyjen yhteydessä. Olioihin toteutetaan erityisiä tapahtumakäsittelijöitä (slots), jotka voidaan yhdistää yhteen tai useampaan signaaliin. Qt huolehtii siitä, että signaalin saapuessa kaikkia siihen sidottuja tapahtumakäsittelijöitä kutsutaan. Tällä mekanismilla saadaan eroteltua tapahtuman aiheuttava osuus sen käsittelijästä, jolloin vastuunjako ohjelman sisällä on selkeämpää.
Monet Qt:n laajennukset, kuten tapahtumapohjainen ohjelmointi ja sidonta Qt Quickiin, vaativat ajonaikaisesti tietoa ohjelman ja olioiden rakenteesta. C++-kielestä puuttuu kuitenkin standardoitu tuki ajonaikaiselle metainformaatiolle. Tästä johtuen Qt:n käännösympäristöön on integroitu esikääntäjä, joka tallentaa sovelluksen ja olioiden rakenteesta metainformaatiota käännösvaiheessa. Tämän mekanismin ansiosta Qt-ohjelmilla on käytettävissään paremmat ajonaikaiset metaohjelmoinnin mahdollisuudet kuin C++-ohjelmilla yleensä.
Ohjelmointirajapinta on selkeä ja hyvin dokumentoitu
Qt:n ohjelmointirajapinta (API) on hyvin dokumentoitu, selkeä ja yhtenäinen - etenkin ottaen huomioon, että kirjastoa on kehitetty lähes 20 vuotta. Qt:n kehittäjät ovat alusta asti panostaneet kirjaston rajapinnan laatuun ja dokumentoineet rajapintasuunnitteluperiaatteensa.
Merkittävin heikkous on historiallisista syistä puuttuva tuki C++-kielen poikkeuksille (exception) ja niiden ajonaikaisten virheiden hallinnalle. Qt:n historiaan on mahtunut myös poikkeuksia rajapintojen laadun tasossa. Esimerkiksi käyttöliittymän sommittelu Qt Quickia edeltäneillä QGraphicsWidgeteillä on paikoitellen hankalaa, ja halutun näkymän aikaansaaminen voi vaatia paljon aikaa ja vaivaa.
Qt takaa sovellusten binääriyhteensopivuuden kirjaston saman pääversion sisällä. Version vaihtuessakin muutokset pyritään minimoimaan, jotta sovellusten siirtäminen uuteen versioon olisi mahdollisimman vaivatonta.
Heikkoutena huono testattavuus
Qt-sovellusten yksikkötestaaminen on melko hankalaa. C++-maailmassa yksikkötestaaminen ja testattavuuteen panostaminen ei ole yhtä yleistä kuin esimerkiksi Java-maailmassa. Oman sovelluksen Qt-riippuvuuksien eristäminen ja korvaaminen testitoteutuksilla saattaa olla työlästä tai jopa joissakin tapauksissa mahdotonta.
Testausvetoinen kehitys ja testaustyökalut ovat Qt:ssa muuta alustaa jäljessä. Testauskoodin määrän suhde Qt:n tuotantokoodiin on noin 20 % Qt:n versioissa 4.7 ja 4.8. Koska Qt:n omassa kehityksessä ei ole vahvaa yksikkötestauskulttuuria, on luonnollista, että myöskään Qt:ta käyttävien sovellusten testattavuus ei ole niin hyvä kuin se voisi olla.
Qt tarjoaa kehittäjille QTestLib-nimisen yksikkötestauskehyksen. Se toimii mainiosti yksinkertaisten yksikkötestien toteutuksessa, mutta on muuten toiminnallisuudeltaan suppea.
Käyttöliittymä QML:llä
Qt:n pääasiallinen tapa käyttöliittymän tekoon on uusimmissa versioissa Qt Quick. Sen tärkein osa on JavaScriptiin perustuva QML-ohjelmointikieli. Se on dynaamisesti tyypitetty tulkattava kieli, jota ajetaan virtuaalikoneessa natiivin ohjelmakoodin rinnalla.
Qt Quickin sisältämän ajoympäristön avulla QML integroituu natiiviin koodiin, jolloin osa sovelluksesta voidaan toteuttaa C++:lla. Natiivikoodi on tehokkaampaa, ja sillä on monipuolisemmat mahdollisuudet hyödyntää Qt-kirjaston tarjoamia palveluita. Joitakin sovelluksia voidaan toteuttaa pelkällä QML:llä, mutta etenkin suuremmassa sovelluksessa myös natiivikoodia tarvitaan usein.
Natiivikoodilla toteutettu ydin tarjoaa rajapinnan, jonka kautta QML-käyttöliittymä ja natiiviydin kommunikoivat. Ydin- ja käyttöliittymäosien selkeän vastuujaon ja hyvin toteutetun rajapinnan avulla sovelluksen ylläpito helpottuu. Esimerkiksi pelkkään ulkonäköön liittyvät muutokset voidaan usein toteuttaa pelkkää QML-koodia muokkaamalla.
Kokonaan uudentyyppinen käyttöliittymä, kuten työpöytäkäyttöön tehdyn sovelluksen mobiiliversio, kannattaa toteuttaa yksinkertaisesti kirjoittamalla sitä varten uusi QML-käyttöliittymäkoodi. Pelkkää QML:ää muuttamalla sovelluksen muokkaaminen on mahdollista vain rajallisesti. Käytännössä myös natiiviydin ja rajapinta vaativat aina muutoksia. Hyvä rajapintasuunnittelu ja selkeä vastuunjako helpottavat uusiin tarpeisiin mukautumista.
QML muistuttaa JavaScriptmäisen luonteensa takia paljon web-sovelluskehitystä. Esimerkiksi animaatiot ja tapahtumakäsittelijät ovat toteutettavissa pienellä määrällä koodia. QML:n tarjoama malli käyttöliittymäkomponenttien kytkemiseen toisiinsa tuntuu luonnolliselta. Vastaavien mekanismien voisi toivoa yleistyvän muissakin käyttöliittymien tekoon tarkoitetuissa ympäristöissä.
Teknologian tuoreuden takia parhaat QML-käytännöt hakevat vielä muotoaan. Ympäristö itsessään ei pakota esimerkiksi erittelemään rakennetta, toiminnallisuutta ja ulkoasun tyylittelyä, vaan näiden huomioiminen vaatii tiimiltä sovittuja käytäntöjä ja kuria. Mikäli näistä ei pidetä huolta, voi QML-sovelluksesta tulla työläs kehittää ja ylläpitää.
Pääasiallinen käyttöliittymäpuolen kehitystyö Qt-kirjastoissa on jo jonkin aikaa keskittynyt Qt Quickiin. Joissain sovelluksissa, kuten peleissä, raskaammasta ajoympäristöstä johtuva korkeampi muistinkulutus ja lisääntyneet tehovaatimukset saattavat olla liikaa, joten Qt Quickin rinnalla on tarvittaessa mahdollisuus käyttää pelkkään natiivikoodiin perustuvia kirjastoja.
Qt Creator on kilpailukykyinen kehitysympäristö
Qt tarjoaa sovelluskehyksen lisäksi työkaluja ohjelmoijalle. Näistä tärkein on kirjaston mukana tuleva sovelluskehitysympäristö, Qt Creator, jota markkinoidaan osana Qt Quickia. Qt Creator on räätälöity Qt-kehitykseen, mutta sitä voi käyttää myös muuhun C++-kehitykseen.
Toimiva kehitysympäristö on tärkeä osa hyvää ohjelmointikokemusta. Qt Creatorin kehittämiseen on panostettu. Se sisältää monia hyödyllisiä C++-maailmassa harvinaisia ominaisuuksia, kuten koodin täydennys, kirjoituksen aikainen syntaksin tarkistus sekä monipuolinen koodinavigointi. Ominaisuudet yhdistettynä nopeuteen tekevät Qt Creatorista kilpailukykyisen verrattuna muihin avoimen lähdekoodin C++-IDE:ihin.
Qt Creator nojautuu alustan tarjoamiin työkaluihin. Koska työkalut ovat alustasta riippuen erilaisia, ei integraatio ole aina saumatonta. Käyttökokemus ei yllä aivan samalle tasolle kuin esimerkiksi Visual Studiossa tai XCodessa.
Linuxilla Qt Creator on varteenotettava vaihtoehto C++-kehitykseen, vaikka Qt ei olisikaan varsinainen kohdeympäristö. Kun kirjoitetaan Qt-ohjelmistoa, on Qt Creator kelpo valinta kaikilla alustoilla Qt:lle räätälöityjen ominaisuuksiensa ansiosta.
Qt helpottaa sovelluskehitystä C++:lla
Natiivikoodin kirjoittamisessa on aina omat haasteensa, ja etenkin C++ on kielenä tunnetusti monimutkainen. Qt helpottaa sovelluskehitystä C++:lla ja tarjoaa hyviä työkaluja. Esimerkiksi Javascriptiin pohjautuva QML on innovatiivinen teknologia, jonka esittelemä malli käyttöliittymien toteuttamiseen tuntuu luontevalta.
Vaikka Qt helpottaa alkuun pääsyä ja parantaa tuottavuutta, on syvällisemmästä C++-osaamisesta hyötyä myös Qt:ta käytettäessä.
