TIE-20200 Ohjelmistojen suunnittelu Luento 9: Kirjastot, pluginit jne. TIE-20200 Samuel Lahtinen 1
Ajankohtaista Viikkoharjoituksissa kirjastojen käyttöä & toteuttamista Kurkkaaminen viime viikon viikkoharkkajuttuihin
Ohjelmassa tänään Viime viikon rääppeitä, rakennuttajajutut loppuun RAII Kirjastoista ja plugineista
Resource Acquisition is Initialization (RAII) Programming idiom (C++), ei siis suunnittelu/toteutusmalli (yleistettävyys) Idea: resurssin vapauttamisesta huolehtii purkaja (ja varaamisesta rakentaja) Resurssin varaus näkyvyysalueen mukaan, automaattinen vapauttaminen, ei muistamisongelmaa/poikkeustilanneongelmaa jne. Tiedostojen, kuvaresurssien, mutexien yms. vastaavien asioiden käyttö kääritään varaaminen rakentajaan ja vapauttaminen purkajaan. Käytetään käärijää(wrapper) vain staattisesti, ei dynaamisen muistinvarauksen kanssa automaattinen vapautus kun näkyvyysalue päättyy
Poikkeusturvallisuus ja RAII Poikkeusturvallisuus ja C++:n sudenkuopat Esimerkkejä potentiaalisista ei-turvallisista toimenpiteistä File initfile; initfile.open( "init.txt" ); // potentiaalinen riski, poikkeus täällä ja tiedostoa ei suljeta missään initializestufffromfile( f ); initfile.close(); Resource* resource = new Resource( ); // turvatonta, jos tulee poikkeus, delete jää kutsumatta useresourceinotherplace( resource ); delete resource; Lock* lock = getlock(); lock.aquire(); // jos tulee poikkeus, lukitus jää vapauttamatta (ja ohjelma todennäköisesti jämähtää) dosomething(); lock.release();
Mutex-esimerkki std::mutex mymutex; void huonoesimerkki() { mymutex.lock(); dostuff(); // Huono juttu, jos dostuff voi heittää poikkeuksia, jää mutex // vapauttamatta ja ohjelma todennäköisesti lukkoon (deadlock) mymutex.unlock(); } void parempiesimerkki() { std::lock_guard lk( mymutex ); // RAII-mallin mukainen std::lock_guard (lukitsee // rakentajassa mutexin) dostuff(); } // <- lock_guard:in purkaja vapauttaa mutexin
Yhteenveto Olioiden luomiseen liittyvät mallit/patternit, helpottavat laajennettavuutta, vähentävät suoria toteutusriippuvuuksia Lisäävät koodin määrää, tekevät ohjelmasta hieman monimutkaisemman Usein erittäin hyödyllisiä ohjelman muokattavuuden ja laajennettavuuden säilyttämiseksi TIE-20200 Samuel Lahtinen 7
Kirjastot Yleiskäyttöinen, valmis koodi jaetaan yleensä valmiiksi käännettynä Ei tarvetta muuttaa, ei tarvetta nähdä lähdekoodia, säästetään aikaa käännösvaiheessa jne. Valmiin koodin levittäminen isona kasana objektitiedostoja vähemmän kätevää Fiksumpaa yhdistää kaikki objektitiedostot kirjastoksi, joka linkitetään mukaan ohjelmaan Käyttöön tarvitaan otsikkotiedosto (include) ja kirjasto (jossa käännetty koodi)
Kirjastotyyppejä Käännösaikaiset kirjastot Kirjastosta käytössä olevat osat linkitetään osaksi ajettavaa ohjelmaa Kirjaston konekoodi mukana jokaisessa ohjelmatiedostossa (vie tilaa) Uusi versio kirjastosta vaatii uudelleen linkkaamisen jotta ohjelmisto pystyy käyttämään sitä Ajonaikaiset kirjastot (dll, shared libraries) Linkatessa kirjataan, mitä kirjastoa tarvitaan Käynnistyksen yhteydessä tarvitut kirjastot ladataan Kirjastojen täytyy löytyä jostain (ja olla rajapinnoiltaan samaa versiota kuin niiden käyttäjät)
Jaetut/dynaamiset kirjastot Natiivisti käännettävät kielet (esim. C++) Vaativat käyttöjärjestelmä/ympäristökohtaisten kirjastojen/palveluiden käyttöä ajoaikaiseen yhdistämiseen Ei suoraan osa kieltä Tulkattavat kielet, virtuaalikoneympäristöt, yms. ajoympäristöt Tulkattavat kielet, tulkki ajaa ohjelmaa, joten kirjastokoodit jne. uusimman version mukaan (esim. Javascript), viitataan koodiin ja tiedostoihin, ei varsinaisiin kirjastoihin. Kirjaston ero tavalliseen kehityksessä olevaan koodin lähinnä koodin tiiveys Java, virtuaalikone jne. Esimerkkiä: https://www- 01.ibm.com/support/knowledgecenter/SSMKHH_10.0.0/com.ibm.etools.mft.doc/bc23072_.htm.Net ja jaetut kirjastot, esim. C#... oma ajoympäristö tarjoaa keinoja pakettien ja kirjastokomponenttien hallintaan. Esimerkki, Windows.net DLL sisältää: CLR (common language runtime) otsikkotiedostot, CLR metadata, PE (portable executable) otsikkotiedosto (win32), itse natiivi sovellus/kirjastotieto
Liitännäisohjelman rakenteesta Pääohjelma itsenäinen kokonaisuus, voi toimia ilman liitännäisiä (liitännäiset voivat olla ladattavissa myös ajoaikaisesti) Pääohjelma tarjoaa liitännäisille: Rekisteröintipalveluita Rajapinnan, jonka liitännäinen toteuttaa Yleensä Mahdollisuuden resurssien/tiedon vaihtoon (pääohjelma liitännäinen) Joko pääohjelma tarjoaa niitä kutsuessaan liitännäisen palveluita tai pääohjelma paljastaa rajapintoja, joista palveluihin pääsee käsiksi (API) Liitännäinen toteuttaa annetun rajapinnan, tarjoaa pääohjelmalle rajapinnan mukaisia palveluita (usein tee toiminto-henkisiä) TIE-20200 Samuel Lahtinen 11
Rakenne Liitännäisen rajapinta Liitännäisten hallitsija liitännäinen Tarjotut palvelut Ohjelman liitännäiselle mahdollisesti tarjoama(t) rajapinta/rajapinnat TIE-20200 Samuel Lahtinen 12
Kysymyksiä: plussaa/miinusta Mitä hyvää/huonoa staattisissa, dynaamisissa tai pluginratkaisuissa? Mitä vaatimuksia kukin asettaa (ohjelman suunnittelun kannalta)? Milloin käyttäisit mitäkin lähestymistapaa? Kohdekäyttäjät: viihde, työ, teollisuus, julkinen/yritysten sisäiseen käyttöön Ennustetut päivitystarpeet (jatkuvat päivitykset, monia toimittajia, harvat päivitykset/asennus firman toimesta) Asentaminen, ilman asennusohjelmaa/asennusohjelman kera Ohjelman koko (iso vs. pieni)
vastauksia Staattisesti linkitettävät +yksinkertainen, saman ympäristön sisällä siirrettävä +helppo asentaa, käyttää, kaikki samassa -vie enemmän tilaa/muistia (jos ohjelmasta useita instansseja ajossa/jos samaa kirjastoa käyttäviä ohjelmia paljon, -päivittäminen == koko köntin vaihtaminen, jos ohjelman koko kasvaa, huono ratkaisu Dynaamisesti linkitettävät +jaettu kirjasto, tilankäyttö vähenee, voidaan päivittää koskematta sitä käyttäviin ohjelmiin, voidaan päivittää ohjelmaa osa kerrallaan -eri versiot kirjastoista, keskinäinen yhteensopivuus, riippuvuuspolut, samalla koneella voi olla useampia versioita samasta kirjastokomponentista, koko paketista huolehtiminen (vaatii yleensä asennusohjelmia, erillisiä päivitysohjelmia)
vastauksia Plugin-ratkaisut +mahdollista latailla ajoaikaisestikin, vaihtaa, laajentaa, lisätä +voidaan tarjota käyttäjäyhteisölle/muille firmoille mahdollisuus laajentaa omaa ohjelmistoa, uutta toiminnallisuutta jne. ilmaiseksi -laajennettavuuden suunnittelu ja toteutus vievät aikaa/resursseja -laajennusrajapinnat suunniteltava huolella (turvallisuus, toimivuus) -liitännäiset saattavat rikkoa/kaataa hyvin toimivan pääohjelmankin -jos muut saavat tehdä laajennuksia, kuka tekee laadunvarmistuksen/turvallisuusvarmistukset?
Ajoaikaiset kirjastot Mitä voidaan muuttaa ilman että kirjastoa käyttävää ohjelmaa tarvitsee päivittää? Toteutus: kunhan noudatetaan sopimussuunnittelun mukaisesti jälki- ja esiehtoja Rajapinta: Yleisohje, ei saa muuttaa Tarkemmin: Uusien ei-virtuaalisten funktioiden lisääminen mahdollista Vanhojen funktioiden muuttaminen, uusien virtuaalifunktioiden lisääminen myös kirjaston käyttäjät pitää kääntää uudelleen
Jaetut/dynaamiset kirjastot Ja asennukset Asennus tärkeää, minne kirjastokomponentit tulevat, että ohjelmat löytävät ne? vaihtoehtoja: Käyttöjärjestelmän hakemistoihin Ohjelman ajohakemiston alihakemistoon Erilliseen kirjastohakemistoon Mitä mukaan? C++, itse dll ja otsikkotiedostot, jos halutaan tukea muita kehittäjiä? Myös kehitystyökalun kirjastot Esim Qt:n kanssa http://doc.qt.io/qt-5/windows-deployment.html Yleensä asennusohjelma tarpeen/hyödyllinen
Qt ja kirjastokomponentit Qt tarjoaa mahdollisuuden luoda kirjastokomponentteja ja dynaamisesti ladattavia ohjelman osia Hyödyntää käyttöjärjestelmien päälle tehtyjä palveluita (oma sovitus, Linux, Windows, Mac versioille) Mahdollisuus laajentaa Qt:ta tai omaa sovellusta
Qt ja kirjastokomponentit Jotain linkkejä: https://blog.g3rt.nl/building-cpp-shared-libraries-qtcreator.html http://doc.qt.io/qt-5/qtwidgets-tools-plugandpaintexample.html http://doc.qt.io/qt-5/plugins-howto.html http://doc.qt.io/qt-5/qpluginloader.html Windows ja DLL:t https://support.microsoft.com/en-us/kb/815065
Yhteenveto Kerrattiin olioiden elinaikaa ja kopiointijuttuja Opittiin C++-koodarin hyvä ystävä RAII (tämä ei roskienkeruujärjestelmässä toimikkaan näin kivasti) Opittiin jaetun ja staattisen kirjaston peruspiirteistä Opittiin peruskäsitteistöä kirjastoista ja plugineista. Jatkossa myös jotain toteutustavoista jne. TIE-20200 Samuel Lahtinen