52
DOCTRINE 2 ORM JA ZEND FRAMEWORK 2 SOVELLUKSEN JATKOKEHITYKSEN VÄLINEINÄ Case: Matkalaskujärjestelmä Juho Pentinmikko Opinnäytetyö Toukokuu 2016 Tietojenkäsittelyn koulutusohjelma

DOCTRINE 2 ORM JA ZEND FRAMEWORK 2 SOVELLUKSEN … · 2018. 10. 2. · Doctrine 2 ORM and Zend 2 Framework in Further Development of a Software Appli-cation . Case: Travel Expense

  • Upload
    others

  • View
    11

  • Download
    0

Embed Size (px)

Citation preview

Page 1: DOCTRINE 2 ORM JA ZEND FRAMEWORK 2 SOVELLUKSEN … · 2018. 10. 2. · Doctrine 2 ORM and Zend 2 Framework in Further Development of a Software Appli-cation . Case: Travel Expense

DOCTRINE 2 ORM JA ZEND FRAMEWORK 2 SOVELLUKSEN JATKOKEHITYKSEN

VÄLINEINÄ

Case: Matkalaskujärjestelmä

Juho Pentinmikko

Opinnäytetyö Toukokuu 2016

Tietojenkäsittelyn koulutusohjelma

Page 2: DOCTRINE 2 ORM JA ZEND FRAMEWORK 2 SOVELLUKSEN … · 2018. 10. 2. · Doctrine 2 ORM and Zend 2 Framework in Further Development of a Software Appli-cation . Case: Travel Expense

TIIVISTELMÄ

Tampereen ammattikorkeakoulu Tietojenkäsittelyn koulutusohjelma PENTINMIKKO, JUHO: Doctrine 2 ja Zend Framework 2 sovelluksen jatkokehityksen välineinä Case: matkalaskujärjestelmä Opinnäytetyö 52 sivua Toukokuu 2016

Opinnäytetyöni tavoitteena oli tutkia Doctrine 2 ORM -oliorelaatiomapperin sekä Zend Framework 2 sovelluskehyksen soveltuvuutta jo olemassa olevan sovelluksen jatkoke-hitystyöhön. Opinnäytetyön toimeksiantajana oli Evolvit Oy, jonka asiakas X oli uudis-tamassa toiminnanohjausjärjestelmäänsä kuuluvaa matkalaskuraportointia. Opinnäyte-työni tarkoituksena oli saada toimeksiantajan käyttöön työsuunnitelma, jota noudatta-malla matkalaskuraportointi voitaisiin uudistaa. Opinnäytetyö toteutettiin tapaustutki-muksena, jonka esimerkkitapauksena toimii edellä mainittu matkalaskujärjestelmä. Opinnäytetyössä on perehdytty Doctrine 2:n ja Zend Framework 2:n keskeisimpiin ominaisuuksiin sekä kummankin työkalun avulla saavutettavissa oleviin hyötyihin. Opinnäytetyön päätelmistä voidaan todeta, että kummatkin tutkimuksen kohteena olleet työkalut soveltuivat jatkokehitykseen hyvin ja helpottavat ohjelmistokehittäjän työtä: Doctrine 2 vapauttaa kehittäjän rutiininomaisten tietokantakyselyiden kirjoittamiselta ja mahdollistaa helpon tavan tallentaa olioita suoraan tietokantaan. Zend Framework 2:n avulla taas voidaan jakaa ohjelman rakenne helposti MVC -mallin mukaisiin osiin. Opinnäytetyön tuloksena Evolvit Oy:n asiakkaalle saatiin suunniteltua tämän haluama uudistus matkalaskujen syöttämistä varten.

Asiasanat: php, doctrine 2, zend framework 2, oliorelaatiomappaus

Page 3: DOCTRINE 2 ORM JA ZEND FRAMEWORK 2 SOVELLUKSEN … · 2018. 10. 2. · Doctrine 2 ORM and Zend 2 Framework in Further Development of a Software Appli-cation . Case: Travel Expense

ABSTRACT

Tampereen ammattikorkeakoulu Tampere University of Applied Sciences Degree programme in Business Information Systems PENTINMIKKO, JUHO: Doctrine 2 ORM and Zend 2 Framework in Further Development of a Software Appli-cation Case: Travel Expense Report Bachelor's thesis 51 pages, appendices 0 pages April 2016

The goal of this thesis was to examine the applicability of Doctrine 2 ORM object rela-tion mapper and Zend Framework 2 in further development of a pre-existing software application. This thesis was commissioned by Evolvit Oy. The company has a customer who was in need of revising to their ERP system’s travel expense reporting component. This thesis was carried out as a case study. The case studied was the aforementioned revision of the travel expense reporting component. This thesis presents the key features of Doctrine 2 ORM and Zend Framework 2 and the advantages in the development process that are possible to attain by using these tools. As a conclusion of this thesis it can be stated that both of the tools that were examined were well suited for further development of a pre-existing software application: Doc-trine 2 frees the programmer from the tedious task of writing routine database queries and also makes the process of storing object data straight into database relatively easy. With the use of Zend Framework 2 the program structure can be divided into compo-nents according to the MVC design pattern. A plan for the execution of the desired improvements was conceived as a result of this thesis.

Key words: php, doctrine 2, zend framework 2, object relational mapping

Page 4: DOCTRINE 2 ORM JA ZEND FRAMEWORK 2 SOVELLUKSEN … · 2018. 10. 2. · Doctrine 2 ORM and Zend 2 Framework in Further Development of a Software Appli-cation . Case: Travel Expense

4

SISÄLLYS

1 JOHDANTO ................................................................................................................ 7

2 OLIO-RELAATIOMALLINNUS ............................................................................... 8

2.1 Relaatiomalli ........................................................................................................ 8

2.2 Oliomalli ja olio-ohjelmointi ............................................................................. 11

2.3 Olio-relaatiomappaus ......................................................................................... 15

3 Doctrine 2 ORM ........................................................................................................ 18

3.1 Doctrine 2:n esittely ........................................................................................... 18

3.2 Doctrine 2:n perustoiminnot .............................................................................. 18

3.3 Doctrine 2:n EntityManager .............................................................................. 19

3.4 Doctrine 2:n konfigurointi ................................................................................. 20

3.5 Doctrine 2:n entiteetit ........................................................................................ 21

3.6 Doctrine 2:n annotaatiot ..................................................................................... 22

3.7 Doctrine 2:n Entity Repository .......................................................................... 25

3.8 Doctrine 2:n proxyluokat ................................................................................... 26

3.9 Doctrine 2:n komentorivityökalut ...................................................................... 28

3.9.1 Orm:convert ............................................................................................ 28

3.9.2 Orm:generate ........................................................................................... 28

3.9.3 Orm:schema-tool ..................................................................................... 29

3.9.4 Orm:schema-validate .............................................................................. 29

4 ORM:N HYÖDYT JA HAITAT ............................................................................... 30

4.1 Hyödyt ............................................................................................................... 30

4.1.1 Ajan säästäminen ja turhan työn välttäminen ......................................... 30

4.1.2 Ylläpidettävyyden helpottuminen ........................................................... 31

4.1.3 Tietokantariippumattomuus .................................................................... 31

4.2 Haitat .................................................................................................................. 31

4.2.1 Liika abstraktio........................................................................................ 31

4.2.2 Virheen etsinnän vaikeutuminen ............................................................. 31

4.2.3 Suorituskykyyn liittyvät asiat .................................................................. 32

5 ZEND FRAMEWORK 2 .......................................................................................... 33

5.1 Yleistä sovelluskehyksistä ................................................................................. 33

5.2 MVC-suunnittelumalli ....................................................................................... 33

5.3 Zend Framework 2:n esittely ............................................................................. 35

5.4 Zend Framework 2:n moduuli ........................................................................... 36

5.5 MVC -malli ja Zend Framework 2 .................................................................... 36

6 ASIAKKAAN ONGELMA ...................................................................................... 38

6.1 Asiakkaan X toiminnanohjausjärjestelmä ......................................................... 38

Page 5: DOCTRINE 2 ORM JA ZEND FRAMEWORK 2 SOVELLUKSEN … · 2018. 10. 2. · Doctrine 2 ORM and Zend 2 Framework in Further Development of a Software Appli-cation . Case: Travel Expense

5

6.2 Järjestelmän nykytila ......................................................................................... 38

6.2.1 Ohjelmakoodi .......................................................................................... 38

6.2.2 Tietokanta ................................................................................................ 39

6.3 Kilometrikorvausten laskennassa ilmennyt vika ............................................... 40

6.4 Kilometrikorvauksien laskennan korjaaminen .................................................. 41

6.5 Muutostöiden toteuttaminen .............................................................................. 43

6.5.1 Tietokanta ja entiteetit ............................................................................. 43

6.5.2 Tiedon validointi ..................................................................................... 43

6.5.3 Näkymät .................................................................................................. 45

6.5.4 Kontrollerit .............................................................................................. 48

7 JOHTOPÄÄTÖKSET JA POHDINTA .................................................................... 49

7.1 Doctrine 2 .......................................................................................................... 49

7.2 Zend 2 Framework ............................................................................................. 50

7.3 Pohdintaa ........................................................................................................... 51

LÄHTEET ....................................................................................................................... 52

Page 6: DOCTRINE 2 ORM JA ZEND FRAMEWORK 2 SOVELLUKSEN … · 2018. 10. 2. · Doctrine 2 ORM and Zend 2 Framework in Further Development of a Software Appli-cation . Case: Travel Expense

6

LYHENTEET JA TERMIT

ANNOTAATIO Metadataa sisältävä dokumenttilohko

DQL Doctrine Query Language, Doctrine 2:n kyselykieli

DDL Data Definition Language, tietokannan määrittelyyn käytetty

SQL-kielen osa

ENTITEETTI Tietokannan taulua vastaava luokka, josta voidaan muodos-

taa olioita, jotka voidaan tallentaa suoraan tietokantaan

Doctrine 2:n avulla

HYDRATE Täyttää olio tietokannasta löytyvällä tiedolla

JSON JavaScript Object Notation

ORM Object-Relation Mapping

MVC Model-View-Controller -suunnittelumalli eli malli-näkymä-

käsittelijä -suunnittelumalli

YAML YAML Ain’t Markup Language, ihmisluettava datan seria-

lisointikieli

Page 7: DOCTRINE 2 ORM JA ZEND FRAMEWORK 2 SOVELLUKSEN … · 2018. 10. 2. · Doctrine 2 ORM and Zend 2 Framework in Further Development of a Software Appli-cation . Case: Travel Expense

7

1 JOHDANTO

Tämän opinnäytetyön tavoitteena on tutkia Doctrine 2 ORM olio-relaatiomapperin ja

Zend Framework 2:n toimintaa sekä selvittää näiden työkalujen tarjoamia mahdolli-

suuksia ja soveltuvuutta jo olemassa olevan sovelluksen jatkokehityksen välineinä.

Opinnäytetyössäni käyn läpi lyhyesti relaatiomallin ja oliomallin perusteet, kuinka nä-

mä liittyvät toisiinsa, mitä ongelmia relaatiomallin ja oliomallin välillä on. Selvitän

myös mitä tarkoittaa olio-relaatiomallinnus yleisellä tasolla. Tarkoituksena on antaa

selkeä kuva siitä, mihin ongelmaan olio-relaatiomallinnus tarjoaa ratkaisun.

Tämän lisäksi selvitän esimerkkien avulla Doctrine 2 ORM -olio-relaatiomapperin sekä

Zend Framework 2 sovelluskehyksen keskeisimpiä toimintoja. Samalla tehdään katsaus

osista, joista työkalut rakentuvat. Doctrine 2:ta käsittelevien kappaleiden lopuksi käyn

läpi muutaman yleisesti esitetyn mielipiteen ORM -tuotteiden hyödyistä ja myös muu-

tamia kriittisempiä näkökulmia asiaan liittyen.

Työkalujen kuvailun jälkeen käydään läpi työpaikallani Evolvit Oy:llä eteen tullut esi-

merkkitapaus, johon ratkaisumalli suunnitellaan edellä mainittuja työkaluja käyttäen.

Esimerkkitapauksen lähtökohtana toimii Evolvit Oy:n asiakkaan X toiminnanohjausjär-

jestelmän matkalaskutoiminnallisuuksiin tarvittavat uudistustyöt sekä järjestelmässä

havaitut virheet, jotka tulisi uudistustöiden aikana korjata. Opinnäytetyön tarkoituksena

on tehdä toimeksiantajalle työsuunnitelma, jonka pohjalta uudistustyöt voidaan toteut-

taa.

Page 8: DOCTRINE 2 ORM JA ZEND FRAMEWORK 2 SOVELLUKSEN … · 2018. 10. 2. · Doctrine 2 ORM and Zend 2 Framework in Further Development of a Software Appli-cation . Case: Travel Expense

8

2 OLIO-RELAATIOMALLINNUS

2.1 Relaatiomalli

Relaatiotietokanta on yleisin tietokantamalli vielä tänäkin päivänä, vaikka muitakin

malleja tiedon tallentamiseen on tarjolla. Relaatiotietokantojen tapa toimia ja tallentaa

tietoa nojaavat relaatiomalliin, jonka esitti ensimmäisenä Edgar F. Codd vuonna 1970.

(Connolly & Begg 2005: 70.)

Coddin esittämä malli pohjautuu predikaattilogiikkaan, jota en tässä käy läpi. Relaatio-

mallissa tiedot tallennetaan relaatioihin, joita relaatiotietokannoissa kutsutaan tauluiksi.

Tieto tallennetaan mallin mukaisesti monikkoina, jotka taas koostuvat attribuuteista.

Monikkoja kutsutaan tietokannassa riveiksi ja attribuutteja taas kutsutaan sarakkeiksi.

Kuvassa 1. esitetty taulukkoesitys on kaikkein tutuin esitystapa relaatiotietokannassa

oleville tiedoille. (Connolly & Begg 2005, 71–72.)

KUVA 1. Album relaatio ja sen osat.

Relaatiomallissa tiedot esitetään siis riveinä ja sarakkeina. Tietokannan tietyssä sarak-

keessa esitetyt tiedot edustavat aina samaa tietotyyppiä. Sarakkeen tietojen tulisi olla

atomisessa muodossa, toisin sanoen sarakkeen tiedot ovat skalaareja arvoja, eivätkä

täten sisällä arvonansa esimerkiksi toisia attribuutteja tai kokoelmia toisista attribuuteis-

ta. Kuvan 1. artist ja tittle sarakkeet ovat merkkijonotyyppistä tietoa, kun id taas on tie-

totyypiltänsä kokonaisluku.

Relaatiomallissa relaatiot voidaan yhdistää toisiinsa viittaamalla toisessa relaatiossa

esiintyvään uniikkiin arvoon, ns. avain-arvoon.

Page 9: DOCTRINE 2 ORM JA ZEND FRAMEWORK 2 SOVELLUKSEN … · 2018. 10. 2. · Doctrine 2 ORM and Zend 2 Framework in Further Development of a Software Appli-cation . Case: Travel Expense

9

Taulukossa 1. näemme esimerkin tällaisesta tietojen yhdistämisestä. Vasemmalla puo-

lella on relaatio album ja oikealla puolella relaatio artist. Relaatiot yhdistetään toisiinsa

seuraavasti: Relaatiolla album on viittaavana tietona attribuutti artist_id.

Artist -relaatiolla taas on uniikisti relaation monikkoja identifioiva attribuutti id. Asiaa

tarkemmin katsottaessa voidaan havaita, että album -relaation artist_id 3 vastaa artist -

relaation id arvoa 3. Artist -relaation monikossa, jonka id on 3, on artisti nimeltä The

Cheesemakers. Täten album -relaation monikko, jonka id on 7, kuuluu artist relaatiosta

löytyvälle artistille nimeltä The Cheesemakers.

Tiedot esitetään relaatiomallissa edellä osoitetun kaltaisesti linkitettynä toisiinsa, mikä

ehkäisee tiedon moninkertaista tallentamista eli redundanssia. Esimerkkinä voitaisiin

ottaa kuvitteellinen tilanne, jossa pitäisi tallentaa kaikki The Cheesemakersin 256 levyä

tietokantaan. Ei olisi mitään järkeä tallentaa albumin tietoihin 256 kertaa tekstitietona

artistin nimeä, kun kerran on olemassa vain yksi tietty The Cheesemakers -niminen ar-

tisti. Parempi tapa on tallentaa album -relaatioon vain viittaus artist -relaation.

Taulukossa 1. kuvattu relaatioiden välinen yhteys on ns. yhden suhde moneen -yhteys,

joka on varmasti yleisin kaikista tietokannan taulujen välisistä yhteystyypeistä. Relaati-

oiden välillä voi olla myös yhden suhde yhteen tai monen suhde moneen -tyyppisiä yh-

teyksiä.

Yhden suhde yhteen -yhteys merkitsee nimensä mukaisesti tilannetta, jossa relaation

monikkoa vastaa toisessa relaatiossa yksi ja vain yksi monikko. Se ei siis saa esiintyä

toisessa taulussa kuin yhden kerran. Yleensä ottaen yhden suhde yhteen -yhteyksiin

törmää melko harvoin, yksi tyypillinen tilanne, jossa tämä yhteystyyppi tulee kyseeseen,

on ison relaation jakaminen pienemmiksi. Jakamalla iso relaatio pienempiin osiin saate-

taan saavuttaa jonkin asteisia suorituskykyparannuksia. Esimerkkinä tilanne, jossa re-

Page 10: DOCTRINE 2 ORM JA ZEND FRAMEWORK 2 SOVELLUKSEN … · 2018. 10. 2. · Doctrine 2 ORM and Zend 2 Framework in Further Development of a Software Appli-cation . Case: Travel Expense

10

laatio sisältää attribuutteja, joita tarvitaan harvoin, mutta relaatioon tehdään paljon kyse-

lyjä muiden attribuuttien arvoihin. Tällaisessa tilanteessa voi olla suorituskyvyn kannal-

ta edullista jakaa relaatio pienempiin osiin: relaatiosta haetaan vain kiinnostavaa tietoa,

jos halutaan myös ne harvemmin tarvittavat tiedot mukaan, niin liitetään ne mukaan

vain tarvittaessa.

Monen suhde moneen -yhteys taas on huomattavasti paljon yleisempi yhteystyyppi.

Esimerkkinä voitaisiin käyttää tavaran tilausta. Asiakkaan pitää pystyä tekemään tilaus,

johon voi kuulua monta tuotetta. Relaatiot, joita tilauksen tekemiseksi tarvitaan, ovat

siis tilaus ja tuote. Näillä relaatioilla ei kuitenkaan pystytä toteuttamaan annettua vaati-

musta, jonka mukaan tilaukseen voi kuulua monta tuotetta. Tarvitaan uusi relaatio, jota

voitaisiin kutsua nimellä tilaustuote, johon attribuuteiksi tulevat tilaus -relaation yksi-

löivä tieto eli tilaus_id sekä tuote -relaation yksilöivä tieto, tuote_id. Näin saadulla re-

laatiolla voi olla esimerkiksi seuraavanlaiset arvot:

TAULUKKO 2. Monen suhde moneen -liitosrelaatio tilaustuote

Tilaus_id Tuote_id

1 2

2 1

2 2

Tilaukseen numero kaksi kuuluu siis useampia tuotteita. Rakenteellisella tasolla tieto-

kannassa ei ole olemassa suoraa monen suhde moneen -yhteyttä, vaan yhteys muodoste-

taan kahden yhden suhde moneen -yhteyden avulla, kuten kuvasta 2. ilmenee.

Page 11: DOCTRINE 2 ORM JA ZEND FRAMEWORK 2 SOVELLUKSEN … · 2018. 10. 2. · Doctrine 2 ORM and Zend 2 Framework in Further Development of a Software Appli-cation . Case: Travel Expense

11

KUVA 2. Monen suhde moneen -yhteys ilmenee rakenteellisesti kahtena yhden suhde

moneen -yhteytenä.

Tietokannan rakenteellisten ominaisuuksien lisäksi relaatiomalli ottaa kantaa myös da-

tan eheyteen sekä siihen, millaisia operaatioita tiedon käsittelyyn sallitaan. Tiedon

eheyttä voidaan valvoa eheysrajoitteilla (integrity constraints), joista tärkeimpiä ovat

entiteetti eheysrajoite (pääavainrajoite), viite-eheysrajoite sekä arvojoukkorajoite. (Con-

nolly & Begg 2005, 82–83.)

Rajoitteisiin palaan myöhemmin Doctrine 2 annotaatioiden yhteydessä.

2.2 Oliomalli ja olio-ohjelmointi

Olio-ohjelmointi tarkoittaa ohjelmiston rakentamistapaa, joka perustuu ohjelmiston ku-

vaamiseen keskenään kommunikoivina olioina. Olioperustaisuus on yksi ohjelmointi-

malli muiden joukossa eli tapa kuvata järjestelmien rakennetta ja toimintaa. Muita mal-

leja ovat mm. proseduraalinen, funktionaalinen, logiikkaohjelmointi sekä rajoiteohjel-

mointi. Olioperustaisuus vastaa ihmisen tapaa jäsentää maailmaa ja siksi soveltuu muita

malleja paremmin kuvaamaan ohjelmien rakennetta: ihmisen on helpompi hahmottaa

ohjelman rakenne, kun sen käsitemaailma vastaa reaalimaailman asioita. (Koskimies

2000: 21.)

Oliomallin etuina muihin malleihin pidetään helpomman rakenteen jäsentämisen lisäksi

myös seuraavia seikkoja (Koskimies 2000, 23–25).

• Helpompi ylläpidettävyys

• Helpompi laajennettavuus

• Muutosten hallinta

• Koodin uudelleenkäytettävyys

Page 12: DOCTRINE 2 ORM JA ZEND FRAMEWORK 2 SOVELLUKSEN … · 2018. 10. 2. · Doctrine 2 ORM and Zend 2 Framework in Further Development of a Software Appli-cation . Case: Travel Expense

12

Ylläpidettävyyttä ja laajennettavuutta helpottaa oliomallin tapa jakaa ohjelman rakenne

pienempiin, mahdollisimman toisistaan riippumattomiin osiin, jotka näin ollen ovat

mahdollisimman riippumattomia myös kokonaisuuteen kohdistuvista muutosvaatimuk-

sista, muutoksista tai virhekorjauksista: Muutos tai korjaus tarvitsee tehdä vain tiettyyn

kohtaan ohjelmaa, eikä koko järjestelmää tarvitse koodata uudelleen pienen muutoksen

takia. Pienten vaatimusmuutosten tulisi aiheuttaa vain pieniä koodimuutoksia. Tätä

ominaisuutta kutsutaan ohjelmiston jatkuvuudeksi. (Koskimies 2000, 24.)

Koska olio-ohjelmoinnissa ohjelma koostuu toisistaan mahdollisimman toisistaan riip-

pumattomista osista, voidaan toisinaan saada aikaiseksi myös uudelleenkäytettävää oh-

jelmakoodia. Uudelleenkäytettävyys ei ole mikään itsestäänselvyys, vaan vaatii syste-

maattista suunnittelua sen aikaansaamiseksi. Uudelleenkäytettävyyteen tähtäävä suun-

nittelu saattaa joskus olla jopa ristiriidassa sovelluksen käsiteanalyysiin pohjautuvan

suunnittelumenetelmän kanssa. (Koskimies 2000, 25.)

Olio-ohjelmointia ei myöskään voida pitää minään oikotienä onneen ohjelmistokehityk-

sen saralla, se ei esimerkiksi sinällään nopeuta kehitystyötä, pikemminkin päinvastoin:

Analyysi ja suunnitteluvaihe saattavat viedä enemmän aikaa kuin muita malleja käytet-

täessä. Pidempi kehitysaika maksaa kuitenkin usein itsensä takaisin ylläpidon ja laajen-

nettavuuden helppouden tarjoamilla ajallisilla ja taloudellisilla säästöillä. (Koskimies

2000, 25.)

Olio-ohjelmoinnin peruskäsitteitä ovat luokat ja oliot. Oliot ovat malleja reaalimaailman

asioista ohjelman sisällä. Vesterholm ja Kyppö määrittelevät olion seuraavasti: ”Olio on

jokin ympäristöstänsä erottuva kokonaisuus, jolla on oma identiteetti, sisäinen rakenne,

käytös ja viitteet ympäristöönsä. Luokka määrittelee olion rakenteen (attribuutit) ja

käyttäytymisen (metodit). Attribuutit ja metodit muodostavat yhdessä olion piirteet.”

(Vesterholm & Kyppö 2005, 79.)

Olioita ja luokkia mallinnettaessa käytetään yleisesti graafista UML-mallinnuskieltä.

Tämän esityksen puitteissa tulen pitäytymään UML -notaation luokka ja oliokaavion

piirteissä.

Page 13: DOCTRINE 2 ORM JA ZEND FRAMEWORK 2 SOVELLUKSEN … · 2018. 10. 2. · Doctrine 2 ORM and Zend 2 Framework in Further Development of a Software Appli-cation . Case: Travel Expense

13

Olio-ohjelmoinnissa ohjelmakoodia kirjoitettaessa määritellään luokkia, joista ohjelman

ajon aikana syntyy tietokoneen muistiin olioita. Luokkaa voidaan siis ajatella muottina,

jolla voidaan tehdä tietynlaisia olioita. (Vesterholm & Kyppö 2006, 79.)

Aivan kuten relaatiomallissa relaatioilla, myös olioilla on attribuutteja. Attribuutit voi-

vat olla primitiivityyppisiä skalaareja arvoja, kuten levyn nimi, kappaleen järjestysnu-

mero jne. Erotuksena relaatiomallin relaatioihin, joiden attribuuttien arvot ovat lähtö-

kohtaisesti aina skalaareja arvoja, olion attribuutin arvot voivat olla ei skalaareja arvoja,

esimerkiksi toisia olioita tai vaikka taulukoita, jotka sisältävät toisia olioita.

Esimerkkinä oliosta, joka sisältää attribuuttinaan toisia olioita, voidaan käyttää oliota

auto (Kuva 3.). Autolla on reaalimaailmassa ominaisuuksia kuten moottori, renkaat jne.

Lähdettäessä rakentamaan ohjelmaa, joka simuloi reaalimaailman käsitettä auto, voi-

daan melko pian havaita, että kuten reaalimaailman vastineensa, myös ohjelma kannat-

taa rakentaa pienemmistä toisiinsa liittyvistä kokonaisuuksista. Ei ole järkevää kirjoittaa

koodia, jossa kaikki autoon liittyvä asia on yhdessä ja samassa paikassa. Mitä jos halu-

taan vaihtaa autoon erilaiset renkaat, pitääkö silloin tehdä muutoksia autoon? Onko jär-

kevää kirjoittaa koodia, jossa esimerkiksi moottori määritellään erittäin yksityiskohtai-

sesti suoraan auton ominaisuudeksi? Tällöin autoa kuvaavan ohjelmakoodin sisäinen

rakenne voi muodostua riippuvaiseksi moottoria koskevan koodin toiminnasta, jolloin

moottoria kuvaavaan koodiin kohdistuvat muutokset aiheuttavat muutoksia useaan koh-

taan autoa kuvaavaan koodiin.

Parempi tapa on tehdä uusi luokka nimeltä moottori, jonka sisällä määritellään mootto-

rin ominaisuudet, teho, käytetty polttoaine ja vaikkapa sylinterien lukumäärä. Moottori-

luokka voi metodiensa kautta tarjota auto -luokalle rajapinnan, jonka välityksellä auto

käyttää moottori -luokan ominaisuuksia. Näin luokkaan moottori tehtävät muutokset

eivät välttämättä aiheuta muutoksia auto -luokan toimintaan.

Page 14: DOCTRINE 2 ORM JA ZEND FRAMEWORK 2 SOVELLUKSEN … · 2018. 10. 2. · Doctrine 2 ORM and Zend 2 Framework in Further Development of a Software Appli-cation . Case: Travel Expense

14

KUVA 3. Luokat Auto ja Moottori. Moottori -luokan vierellä on moottori -luokasta

luotuja luokan ilmentymiä eli olioita.

Jos kehityksessä käytetään jälkimmäistä tapaa, voidaan tehdä helposti useammanlaisia

auto -olioita, ilman, että tarvitsee muuttaa auto -luokan toteutusta joka kerta kun halu-

taan erilainen auto -olio. Kuvassa 4. on yksinkertaistettu esimerkki autosta ja siihen liit-

tyvistä olioista.

KUVA 4. Auto -oliolla on tietojäseninä muista luokista luotuja olioita.

Hyvin suunnitellut luokat voivat olla sellaisenaan käytettävissä myös irrallaan alkupe-

räisestä käyttökontekstistansa, esimerkkinä käytetty moottori -luokka voisi sellaisenaan

Page 15: DOCTRINE 2 ORM JA ZEND FRAMEWORK 2 SOVELLUKSEN … · 2018. 10. 2. · Doctrine 2 ORM and Zend 2 Framework in Further Development of a Software Appli-cation . Case: Travel Expense

15

olla osana myös ohjelmassa, jossa tarvittaisiin moottoripyörän tai vaikka varavirta-

generaattorin moottoria. Tämä siis karkeana esimerkkinä uudelleenkäytettävästä luokas-

ta.

Oliosta, jonka tietojäsenenä on toisia olioita tai kokoelmia toisista olioista päästään kä-

siksi ongelmaan relaatiomallin ja oliomallin yhdistämisessä: Kuinka tallentaa ei skalaa-

reja arvoja (olioita) relaatiomallin relaatioon, joka lähtökohtaisesti hyväksyy attribuut-

tinsa arvoksi vain skalaareja, atomisia arvoja.

2.3 Olio-relaatiomappaus

Olio-relaatiomappaus on tekniikka, jota käytetään ohjelmointikielissä sovittamaan yh-

teen keskenään erilaiset ja yhtyeensopimattomat tietomallit. (Blanco, Borschel, Vesteri-

nen & Wage 2010, 13.)

Kuten kappaleissa 2.1 ja 2.2 kävi ilmi, relaatiotietokanta lähtökohtaisesti pitää kenttien-

sä tietosisältönä skalaareja arvoja, kuten kokonaislukuja, merkkijonoja jne. Oliot taas

voivat sisältää tietojäseninään myös muita olioita, jolloin oliota ei voi sellaisenaan tal-

lentaa relaatiotietokantaan, niin että sen tiedoista hakeminen olisi helppoa tai järkevää.

Tämä tilanne on havainnollistettu kuvassa 5.

KUVA 5. Oliota, jolla on tietojäsenenään toinen olio ei voida suoraan tallentaa relaatio-

tietokannan tauluun.

Olion tallentaminen tietokantaan on toki mahdollista esim. JSON -muodossa tekstikent-

tään, mutta tällöin hakeminen olion sisältävästä JSON tekstistä on useimmilla tietokan-

tatuotteilla erittäin hankalaa.

Page 16: DOCTRINE 2 ORM JA ZEND FRAMEWORK 2 SOVELLUKSEN … · 2018. 10. 2. · Doctrine 2 ORM and Zend 2 Framework in Further Development of a Software Appli-cation . Case: Travel Expense

16

Jotkin tietokantatuotteet, kuten PostgreSQL ja MySQL tarjoavat uudemmissa versioissa

käyttöön myös JSON -tietotyypin, joka helpottaa olioiden tallentamista ja niiden sisäl-

löstä hakemista, mutta ominaisuuden tarjoamien mahdollisuuksien selvittely on rajattu

tämän työn ulkopuolelle.

Olioiden ja relaatiotietokannan relaatioiden välinen erilaisuus tulee siis ratkaista joko

jakamalla oliot yksiarvoisiksi joukoiksi tietokantaan tallentamista varten tai käyttää vain

yksiarvoisia arvoja ohjelmassa, mikä ei tietenkään ole järkevää.

Olio-relaatiomappausta sovelletaan ensin mainittuun lähestymistapaan. Ongelmana on

siis olioiden muuntaminen sellaiseen muotoon, että ne voidaan tallentaa tietokantaan ja

hakea tietokannasta niin, että olioiden ominaisuudet ja niiden väliset suhteet säilyvät

ennallaan. Jos olioita voidaan käsitellä näin, voidaan sanoa, että oliot ovat pysyviä (per-

sistent objects). (Blanco ym. 2010, 14)

Kun oliot on mapattu oikein relaatiotietokannan tauluihin, niin hakuja voidaan tehdä

järkevästi myös tietokannasta. Se, että kaikki tiedot ovat omissa kentissään, verrattuna

siihen, että tiedot on tallennettu JSON -muodossa tekstikenttään helpottaa oman koke-

mukseni mukaan kehittäjän ja ylläpitäjän työtä huomattavasti.

Olen omassa työssäni törmännyt tapauksiin, joissa ohjelmassa esiintyvän virheen ai-

heuttajan etsiminen tietokannasta on ollut jossain määrin uuvuttavaa. Tämä on johtunut

siitä, ettei tietoa voida suoraan hakea tietokannasta, vaan yhden tietokentän löytämiseksi

on tarvinnut kirjoittaa erikseen koodia, joka purkaa tiedon auki ihmiselle luettavaan

muotoon virheen etsimistä varten.

Olio-relaatiomappauksen tuloksena ohjelman suorituksen aikana tietokoneen muistiin

muodostuu virtuaalinen oliotietokanta, jota voidaan käyttää ohjelmointikielen avulla.

Virtuaalitietokannasta voidaan ohjelmointikieltä hyväksikäyttäen hakea tietoja, ja käsi-

tellä tietoja siten, että tiedot ovat oliomuodossa.

Olio-relaatiomapperi pitää huolen siitä, että tiedot menevät oikeisiin tauluihin ja kent-

tiin, kun tietoa tallennetaan fyysiseen tietokantaan sekä myös siitä, että tieto haetaan

oikeaan olioon fyysisestä tietokannasta tietoa haettaessa.

Page 17: DOCTRINE 2 ORM JA ZEND FRAMEWORK 2 SOVELLUKSEN … · 2018. 10. 2. · Doctrine 2 ORM and Zend 2 Framework in Further Development of a Software Appli-cation . Case: Travel Expense

17

KUVA 6. ORM toimii virtuaalisena oliotietokantana sovelluksen ja tietokannan välissä.

Page 18: DOCTRINE 2 ORM JA ZEND FRAMEWORK 2 SOVELLUKSEN … · 2018. 10. 2. · Doctrine 2 ORM and Zend 2 Framework in Further Development of a Software Appli-cation . Case: Travel Expense

18

3 Doctrine 2 ORM

3.1 Doctrine 2:n esittely

Doctrine 2 on avoimen lähdekoodin ORM ohjelmistokirjasto PHP-kielelle. Doctrine 2

tulee osana Symfony2 sovelluskehystä, mutta toimii myös itsenäisesti missä tahansa

PHP-projektissa. Symfony2:n lisäksi se integroituu erinomaisesti myös Zend Fra-

mework 2, CodeIgniter sekä Laravel sovelluskehysten kanssa. Doctrine 2 on asennetta-

vissa Composer pakettienhallinnan kautta. (Dunglas 2010, 14.)

Doctrine 2 mahdollistaa helpon tavan hakea tietokannasta tietoja suoraan olioksi sekä

tallentaa PHP -olioita tietokantaan ilman, että ohjelmoijan tarvitsee kirjoittaa riviäkään

SQL koodia.

Doctrine 2 pitää sisällään myös SQL:n kaltaisen kyselykielen, DQL:n (Doctrine Query

Language), jonka avulla voidaan kirjoittaa monimutkaisempia kyselyitä, jotka eivät ole

mahdollisia valmisfunktioiden avulla. Siinä on ominaisuutena myös työkalut tietokan-

taskeeman luomiseksi sekä PHP -luokkien luomiseksi valmiina olevasta tietokantas-

keemasta. (Dunglas 2013, 14.)

3.2 Doctrine 2:n perustoiminnot

Doctrine 2 ORM perustuu Data Mapper ja Unit Of Work suunnittelumalleihin:

(Dunglas 2013, 25.)

• Data Mapper on ohjelmistokerros joka erottaa muistinvaraiset oliot tietokannas-

ta. Sen tehtävänä on välittää tietoja näiden välillä sekä eristää ne toisistaan.

Muistinvaraisten olioiden ei tarvitse tietää edes sitä, että onko tietokanta olemas-

sa, ne eivät tarvitse SQL -koodia, eivätkä tietoa tietokannan skeemasta. (Fowler

2003)

• Unit Of Work -mallin avulla pidetään kirjaa olion tilaan suorituksen aikana tul-

leista muutoksista sekä siitä, mitä muutoksia tietokantaan pitää tehdä tehtyjen

operaatioiden jälkeen. Mallin avulla yritetään välttää lukuisia pieniä tietokanta-

kutsuja ja tehdä tarvittavat muutokset yhdellä kertaa. Mallin käyttämisen on tar-

Page 19: DOCTRINE 2 ORM JA ZEND FRAMEWORK 2 SOVELLUKSEN … · 2018. 10. 2. · Doctrine 2 ORM and Zend 2 Framework in Further Development of a Software Appli-cation . Case: Travel Expense

19

koitus nopeuttaa tietokannan käyttöä sekä ehkäistä epäjohdonmukaista tiedonlu-

kua muistissa oleviin olioihin. (Fowler 2003)

Data Mapperin tehtävänä Doctrine 2:ssa on siis tehdä tarvittavat tietokantaan kohdistu-

vat tallennukset ja päivitykset niistä olioista, joita tietokantaan halutaan tallentaa. Data

Mapper myös huolehtii tiedon poistosta tietokannasta tarpeen mukaan eli silloin, kun

olio on merkitty poistettavaksi muistista. Näiden lisäksi Data Mapper huolehtii myös

olion ns. hydrate -operaatiosta eli tiedon hakemisesta tietokannasta muistinvaraiseen

olioon. (Dunglas 2013, 25.)

3.3 Doctrine 2:n EntityManager

Doctrine 2:ssa Data Mapperin tehtävää hoitaa EntityManager -niminen luokka. Nimensä

mukaisesti EntityManager hallitsee entiteeteiksi kutsuttuja olioita. Entiteetit ovat ns.

POPO olioita (Plain Old PHP Objects) eli aivan tavallisia PHP-kielellä määriteltyjen

luokkien instansseja. Entiteetit ovat ohjelmassa malleja tietokannassa esiintyvistä tau-

luista. Jokaista ohjelman ajamiseksi tarvittavaa tietokannan taulua varten Doctrine 2

tarvitsee entiteettiluokan.

EntityManager tarjoaa käytettäväksi seuraavanlaiset perustoiminnot:

• find($entityName, $id, $lockMode, $lockVersion)

o Ottaa parametrina entiteettiluokan nimen, jonka perusteella tietokannas-

ta haetaan tietoa sekä id:n, jolla tietoa haetaan. Palauttaa entiteettiluokan

tyyppisen olion. lockMode sekä lockVersion oletuksena arvoltaan null.

• persist($entity)

o Ottaa parametrina entiteetti instanssin, joka halutaan tallentaa tietokan-

taan. Olion tilaksi tulee persist funktiokutsun jälkeen ”managed”, joka

tarkoittaa sitä, että tieto tallennetaan tietokantaan kutsuttaessa Entity

Managerin flush funktiota tai kommitoitaessa transaktio.

• remove($entity)

o Ottaa parametrina entiteetti instanssin, joka halutaan poistaa tietokan-

nasta. Kuten persist funktio, myös remove ajetaan tietokantaan kutsutta-

essa flush funktiota tai kommitoitaessa transaktio.

• flush($entity = null)

Page 20: DOCTRINE 2 ORM JA ZEND FRAMEWORK 2 SOVELLUKSEN … · 2018. 10. 2. · Doctrine 2 ORM and Zend 2 Framework in Further Development of a Software Appli-cation . Case: Travel Expense

20

o Oletuksena ajaa kaikki managed -tilassa oleviin olioihin kohdistuneet

muutokset tietokantaan eli synkronoi muistinvaraisen virtuaalisen olio-

tietokannan tiedot fyysisen tietokannan kanssa. Mikäli funktiolle anne-

taan parametrina entiteetti, vain tämä entiteetti ja siihen liittyvät mahdol-

liset poistojen sekä päivitysten vyörytykset synkronoidaan tietokantaan.

3.4 Doctrine 2:n konfigurointi

Doctrine 2 tarvitsee toimiakseen konfiguraatiotiedoston (koodiesimerkki 1), jossa mää-

ritetään tietokantayhteyden tarvitsemat tiedot, kuten tietokanta-ajuri, osoite sekä tieto-

kannan nimi. Tämän lisäksi tarvitaan myös bootstrap -tiedosto (koodiesimerkki 2), jolla

Doctrine ”käynnistetään”.

KOODIESIMERKKI 1. Doctrine 2 tietokantakonfiguraatio MySQL -tietokantaa varten.

Yhteydessä käytetään PDO -ajuria.

KOODIESIMERKKI 2. Doctrine 2 -käynnistystiedosto.

Page 21: DOCTRINE 2 ORM JA ZEND FRAMEWORK 2 SOVELLUKSEN … · 2018. 10. 2. · Doctrine 2 ORM and Zend 2 Framework in Further Development of a Software Appli-cation . Case: Travel Expense

21

Koodiesimerkissä 2 konfiguroidaan Doctrine 2 käyttämään annotaatiopohjaista entiteet-

tien mappausta. Annotaatiot ovat kommentti/dokumentti -lohkoon sijoitettuja metatieto-

ja, joiden avulla Doctrine 2:lle kerrotaan, miten sen tulisi toimia. Muita mahdollisia

tapoja tehdä mappaukset on tehdä ne käyttäen XML -merkintää, YAML -merkintää tai

pelkästään PHP -koodia käyttäen.

Vaikka muita tapoja mappausten toteuttamiseksi on olemassa, niin esimerkeissä pitäy-

dyn kuitenkin annotaatiossa. Annotaatioiden eduiksi voidaan lukea parempi koodin lu-

ettavuus sekä helpompi ylläpidettävyys, johtuen siitä, että mappaustiedot ovat koodin

vieressä, eikä niitä tarvitse etsiä monesta paikkaa samanaikaisesti. (Dunglas 2013, 34.)

3.5 Doctrine 2:n entiteetit

Doctrine 2 entiteetit ovat pohjimmiltaan aivan tavallisia PHP -luokkia, jotka vastaavat

tietokannasta löytyviä tietokannan tauluja. Tekemällä tietyt määritykset, nämä luokat

ovat sellaisenaan tallennettavissa tietokantaan. Jos luokan oliolla on tietojäsenenään

toisia olioita, niin myös nämä haetaan ja tallennetaan tietokantaan automaattisesti.

Määrityksiä, joilla edellä mainitut operaatiot hoidetaan, kutsutaan mappaustiedoiksi.

Mappaustiedot taas merkitään käyttäen joko annotaatioita, XML -merkintätapaa,

YAML -merkintätapaa tai pelkkää PHP -merkintätapaa käyttäen. Koodiesimerkissä 3.

on esimerkki yksinkertaisesta entiteettiluokasta.

Page 22: DOCTRINE 2 ORM JA ZEND FRAMEWORK 2 SOVELLUKSEN … · 2018. 10. 2. · Doctrine 2 ORM and Zend 2 Framework in Further Development of a Software Appli-cation . Case: Travel Expense

22

KOODIESIMERKKI 3. Yksinkertainen entiteettiluokka SiltaAccessType.

Koodiesimerkissä 3. on esitetty entiteetti, jolla on attribuutit id ja type. Kummankin

attribuutin yläpuolella on annotaatio, jossa määritellään attribuutin ominaisuuksia. Esi-

merkiksi muuttuja id on typpiä boolean, tyypiltänsä Id ja se on generoitu arvo eli jos

tietonkantana on MySQL, niin kentän arvo muodostetaan käyttäen AU-

TO_INCREMENT tyyppiä.

3.6 Doctrine 2:n annotaatiot

Annotaatiot ovat kaikessa yksinkertaisuudessaan metatietoja dokumenttilohkossa.

Doctrinessa käytetään annotaatioita kuvaamaan entiteetin attribuuttien ja luokkien omi-

naisuuksia, kuten tietotyyppi sekä mappaukseen ja tietokantaan liittyvien tietojen ku-

vaamiseen. Koodiesimerkissä 3 on esimerkki annotaatiosta.

Page 23: DOCTRINE 2 ORM JA ZEND FRAMEWORK 2 SOVELLUKSEN … · 2018. 10. 2. · Doctrine 2 ORM and Zend 2 Framework in Further Development of a Software Appli-cation . Case: Travel Expense

23

KOODIESIMERKKI 3. Annotaatiossa määritetään attribuutin ominaisuudet sekä yh-

teydet muihin luokkiin.

Koodiesimerkissä 3. kuvattu annotaatio on osa SiltaAddress -entiteettiluokan määritte-

lyä. SiltaAddress luokalla on attribuuttina SiltaAccessLog -luokan olio. Tietokannan

puolella silta_address taulussa on vierasavain accesslog_id, jolla viitataan tauluun sil-

taAccesslog. Annotaation osa voidaan lukea selväkielisesti seuraavasti:

• Muuttuja accesslog on tyypiltänsä luokan SiltaAccesslog ilmentymä.

• Yhteystyyppi, jota annotaatiossa käytetään, on yhden suhde moneen -yhteys

• Kohde-entiteetti johon liitos tehdään, on SiltaAccesslog.

• Liitos tehdään tietokannassa siltaAddress -taulun attribuutin accessLog_id ja

taulun siltaAccessLog attribuuttiin id välille.

Annotaatioiden avulla voidaan määritellä myös erilaisia rajoitteita attribuuteille. Kes-

keisimmät rajoitteet, joita yleisesti määritellään, ovat arvojoukkorajoitteet (esim. merk-

kijonon maksimipituus, desimaalirajoittimet jne.), viite-eheysrajoitteet sekä pääavainra-

joite. Koodiesimerkissä 4 on esimerkki arvojoukkorajoitteesta, koodiesimerkissä 5 on

esimerkki viite-eheysrajoitteesta ja koodiesimerkissä 6 on esimerkki pääavainrajoittees-

ta.

Page 24: DOCTRINE 2 ORM JA ZEND FRAMEWORK 2 SOVELLUKSEN … · 2018. 10. 2. · Doctrine 2 ORM and Zend 2 Framework in Further Development of a Software Appli-cation . Case: Travel Expense

24

KOODIESIMERKKI 4. Arvojoukkorajoite, jolla rajataan tuntipalkan kelvolliset arvot

välille 0.00 – 999.99.

Arvojoukkorajoite määritetään annotaation @ORM\Column -kohdassa asettamalla co-

lumnDefinition kohtaan DDL SQL pätkä, tässä tapauksessa SQL CHECK lause.

KOODIESIMERKKI 5. Monen suhde moneen yhteyden määrittely annotaatiossa.

Entiteettien välinen monen suhde moneen -yhteys määritellään koodiesimerkissä 5. ker-

tomalla annotaatiossa Doctrinelle, että kyseessä on monen suhde moneen -yhteys, pa-

rametrina annetaan kohde-entiteetti. Tämän jälkeen liitetään taulut, tässä tapauksessa

tilaaja, ja tilaajan puhelinnumerot eli yhteyden liitostaulu. Join columns -kohdassa ker-

rotaan minkä kenttien avulla liitos tehdään. inverseJoinColumns -kohdassa tehdään lii-

tos kohdetaulun ja liitostaulun välille eli liitetään liitostaulu kohdetauluun. Käytännössä

on siis muodostettu yhden suhde moneen -liitos taulujen tilaaja ja tilaajan puhelinnume-

rot sekä yhden suhde moneen -liitos taulujen puhelinnumero ja tilaajan puhelinnumerot

välille.

Koodiesimerkissä 5 kuvattu tapa tehdä liitoksia on eritäin kätevä siitä syystä, että näin

voidaan säästää melko tavalla aikaa ja turhaa työtä: Käyttämällä Doctrinen komentorivi-

työkaluja, on mahdollista luoda entiteeteistä tai malliluokista tietokantaskeema. Koo-

diesimerkissä kuvattu annotaatio luo komentorivityökalua käytettäessä myös liitostau-

lun automaattisesti eli sitä ei tarvitse erikseen luoda.

Page 25: DOCTRINE 2 ORM JA ZEND FRAMEWORK 2 SOVELLUKSEN … · 2018. 10. 2. · Doctrine 2 ORM and Zend 2 Framework in Further Development of a Software Appli-cation . Case: Travel Expense

25

KOODIESIMERKKI 6. Pääavainrajoitteen määrittely.

Koodiesimerkissä 6 on määritelty pääavainkenttä id. Muuttuja on kokonaislukutyyppi-

nen, tarkkuus 0 (tarkkuutta ei käytetä kokonaisluvuilla), desimaaliskaala 0 (ei käytetä

kokonaisluvuilla), sen arvoksi ei voida asettaa NULL arvoa, ja se ei ole uniikkiavain.

@ORM\Id kertoo Doctrinelle, että tämä kenttä on pääavain. Tämän jälkeen vielä kerro-

taan Doctrinelle, että pääavaimen arvo on automaattisesti generoitu arvo sekä se, että

miten tämä arvo pitäisi muodostaa. Arvon muodostamiseen käytettävissä olevat strate-

giat ovat: (Doctrine Project Team, 74–75.)

• AUTO, oletusarvo, käyttää tietokantatuotteen oletustapaa arvon generoimiseksi,

täysin tietokantariippumaton (tuettujen järjestelmien puitteissa).

• SEQUENCE, käytetään tietokantaan luotua sekvenssiä arvon muodostamiseksi.

Sekvenssin käyttöä tukevat tuotteet: Oracle, PostgreSQL sekä SQL Anywhere.

• IDENTITY, käytetään tietokantatuotteen identity erikoiskenttää. Kentän toimin-

ta vaihtelee tietokantatuotteiden välillä, MySQL, SQLite ja SQL Anywhere

käyttävät AUTO_INCREMENT tapaa, MSSQL käyttää IDENTITY tyyppiä, ja

PostgreSQL tyyppiä SERIAL. Muille tuotteille ei ole tukea.

• UUID, arvon luomiseksi käytetään Doctrinen UUID generaattoria. Tietokanta-

tuoteriippumaton.

3.7 Doctrine 2:n Entity Repository

Ennemmin tai myöhemmin kehitystyössä tulee vastaan tilanne, jossa EntityManager

luokan tarjoamat perustoiminnot eivät enää riitä kyselyiden tekemiseksi kannasta, kyse-

lyissä voidaan tarvita esimerkiksi LEFT JOIN -tyyppisiä liitoksia, joita EntityManager

ei suoraan tarjoa.

Tällaisia tilanteita varten Doctrine 2 tarjoaa käytettäväksi EntityRepository luokasta

periytettävät repositoryluokat. Entiteetille voidaan annotaatiossa kertoa, mitä repository-

Page 26: DOCTRINE 2 ORM JA ZEND FRAMEWORK 2 SOVELLUKSEN … · 2018. 10. 2. · Doctrine 2 ORM and Zend 2 Framework in Further Development of a Software Appli-cation . Case: Travel Expense

26

luokkaa tämän tulisi käyttää. Repositoryluokat on mahdollista generoida automaattises-

ti, josta lisää kappaleessa 3.9.2.

Repositoryluokkiin on mahdollista määritellä omia funktioita, joita voidaan tarpeen

mukaan hakea käytettäväksi. Funktioissa käytetään QueryBuilder -luokasta luotua oliota

kyselyiden rakentamiseen. QueryBuilder -luokan funktioilla on mahdollista luoda kyse-

lyitä koodiesimerkin 7. mukaisesti.

KOODIESIMERKKI 7. Kyselyn luominen QueryBuilderin avulla repositoryluokassa.

Koodiesimerkissä 7. haetaan admin -tyyppisiä käyttäjiä entiteetistä SiltaEmployee. Que-

rybuilderin metodien nimet muistuttavat hyvin paljon perinteistä SQL -syntaksia, jonka

takia sen käyttö on helppo omaksua.

Koodiesimerkissä 7. reporositoryluokkaan luotua omaa kyselyä voitaisiin kutsua käytet-

täväksi seuraavalla tavalla.

KOODIESIMERKKI 8. Repositoryluokassa sijaitsevan funktion kutsuminen.

3.8 Doctrine 2:n proxyluokat

Doctrine 2 käyttää oletuksena assosiaatioiden mappauksessa ns. lazy-loading -

tekniikkaa, joka tarkoittaa sitä, että kun ladataan tietokannasta olio, jolla on assosiaatio

johonkin toiseen olioon, niin tätä assosiaatiota ei ladata välittömästi tietokannasta, vaan

sitä edustaa Doctrinessa sitä varten tehty proxyluokka. ´

Proxyluokka perii aina entiteettiluokkansa ja toteuttaa \Doctrine\ORM\Proxy\Proxy

rajapinnan. (Doctrine Project Team, 36–37.) Proxyluokka voi täten laajentaa entiteetti-

Page 27: DOCTRINE 2 ORM JA ZEND FRAMEWORK 2 SOVELLUKSEN … · 2018. 10. 2. · Doctrine 2 ORM and Zend 2 Framework in Further Development of a Software Appli-cation . Case: Travel Expense

27

luokan toimintaa, mutta pääasiallisesti proxyluokkia käytetään lazy-loading -tekniikan

toteuttamiseksi.

Proxyjen käytölle on pääasiallisesti kaksi syytä:

• Viittaus: Proxyn avulla voidaan viitata johonkin entiteettiin ilman, että sitä hae-

taan tietokannasta.

• Assosiaatio, kun Doctrinessa haetaan olioita, joilla on yksiarvoinen assosiaatio,

eikä kyselyssä tehdä join operaatiota, niin Doctrine luo proxy -olion muistiin, ja

tätä käytetään siihen saakka, kun olion tietoja oikeasti käytetään. Vasta siinä

vaiheessa ladataan tietokannasta olio muistiin.

Esimerkkinä viittausproxysta voitaisiin pitää tilannetta, jossa voidaan asettaa ostosko-

rioliolle tuoteolio, jos tiedetään tuotteen id. Tuotteen tietoja ei haeta tietokannasta muis-

tiin, ellei tuotetta ja sen attribuutteja käsitellä muutoin ohjelman ajon aikana, esim. haeta

tuotteen ominaisuuksia. Jos muita operaatioita tehdään, niin käytetään suoraan entiteet-

tiluokkaa ja tuotteen tiedot haetaan tietokannasta muistinvaraisiksi. Jos ei tuotetta käsi-

teltäisi millään muulla tapaa, säästettäisiin resursseja, koska tuotetta ei tarvitsisi hakea

tietokannasta muistiin ollenkaan.

Esimerkkinä assosiaatioproxystä voitaisiin ottaa työntekijäolio, jolla on assosiaatio

osastoon. Osastoja ei kuitenkaan haeta välittömästi tietokannasta, vaan osastoa varten

luodaan proxy, jossa on viittaustiedot osastoja varten. Jos ohjelman ajon aikana osastoa

koskevia tietoja haetaan, niin proxy häviää välistä ja käytetään suoraan osaston entiteet-

tiluokkaa.

Proxyluokan käyttö on tässä välissä täysin läpinäkyvää eli sen käyttöä tai käyttämättö-

myyttä ei huomata ajon aikana, eikä sen käyttö vaadi välttämättä ohjelmoijalta toimen-

piteitä.

Lazy-loading -tekniikkaan liittyy kuitenkin suorituskykyyn liittyviä ongelmia, jos asso-

siaatioiden määrät ovat suuria: Tietokannasta saatetaan hakea todella suuria määriä rive-

jä kerrallaan, joka hidastaa ohjelman toimintaa.

Proxyluokat voidaan generoida automaattisesti Doctrinen komentorivityökalun avulla,

tästä lisää kappaleessa 3.9.2.

Page 28: DOCTRINE 2 ORM JA ZEND FRAMEWORK 2 SOVELLUKSEN … · 2018. 10. 2. · Doctrine 2 ORM and Zend 2 Framework in Further Development of a Software Appli-cation . Case: Travel Expense

28

3.9 Doctrine 2:n komentorivityökalut

Doctrine 2 tarjoaa kehittäjälle joukon erittäin käteviä komentorivityökaluja, joista mie-

lenkiintoisimmat ovat orm:generate, orm:convert, orm:schema-tool sekä orm:validate-

schema.

3.9.1 Orm:convert

Orm:convert työkalulla voidaan muuntaa mappaustietoja muodosta toiseen eli muuntaa

esimerkiksi XML -muodossa olevat mappaustiedot annotaatioiksi tai YAML -muotoon.

Orm:convert työkalulla on myös mahdollista takaisinmallintaa mappaustiedot jo ole-

massa olevasta tietokannasta.

Takaisinmallinnus on erittäin kätevä työkalu otettaessa Doctrine käyttöön jonkin sovel-

luksen jatkokehitysvaiheessa, sillä vaikkei se generoikaan täydellistä mappaustietoa,

niin ajansäästö suuremmissa projekteissa on huomattavaa. Esimerkiksi 36 taulua sisäl-

tävä työajanhallintaan tarkoitettu tietokanta generoitui annotaatioiksi alle kymmenessä

sekunnissa komentorivityökalun avulla. Annotaatioista generoitujen entiteettiluokkien

yhteenlaskettu koodirivien määrä tässä tapauksessa oli 5964 riviä.

Generoitu mappaustieto ei ole täydellistä, Doctrine projektin dokumentaatiossa maini-

taan, että takaisinmallinnusta käyttäen saavutetaan kuitenkin 70-80 prosenttisesti oikea,

tarvittava mappaustieto. (Doctrine Project Team 2016, 246.)

Hienosäätöä siis tarvitaan, mm. monen suhde moneen -yhteyksien sekä vyörytysmääri-

tyksien kohdalla, joita takaisinmallinnus ei mallinna oikein.

3.9.2 Orm:generate

Orm:generate työkalulla voidaan, kuten nimi antaa olettaa, generoida valitsimesta riip-

puen erilaisia asioita. Generate työkalulle on olemassa seuraavat valitsimet:

• Entities

• Proxies

• Repositories

Page 29: DOCTRINE 2 ORM JA ZEND FRAMEWORK 2 SOVELLUKSEN … · 2018. 10. 2. · Doctrine 2 ORM and Zend 2 Framework in Further Development of a Software Appli-cation . Case: Travel Expense

29

Käyttämällä entities -valitsinta, voidaan generoida mappaustiedoista entiteettiluokat.

Mappaustiedot voivat olla annotaatioina, XML -muodossa tai YAML -muodossa. Valit-

simen optiolla –generate-annotations=”true” on mahdollista luoda generointivaiheessa

myös annotaatiot mukaan generoituihin entiteettiluokkiin. Tämä kannattaa mielestäni

tehdä, sillä se parantaa koodin luettavuutta ja helpottaa ylläpitoa.

Proxies -valitsimella on mahdollista generoida proxyluokkia entiteeteistä. Proxyluokkia

käytetään, jotta on mahdollista ladata muistiin osittaisia olioita tietokannasta. Tätä omi-

naisuutta kutsutaan nimellä lazy-loading.

Repositories -valitsinta käytettäessä Doctrine generoi entiteettien mukaiset Repository-

luokat. Kuten aiemmin mainittu, repositoryluokkia käytetään omien kyselyiden tekemi-

seen.

3.9.3 Orm:schema-tool

Orm:schema-tool -työkalua käytetään tietokantaskeemaan liittyvien operaatioiden suo-

rittamiseen. Schema-tool työkalulla on kolme valitsinta:

• Create, käytetään skeeman luomiseen. Mahdollista luoda mappaustietojen mu-

kainen skeema suoraan tietokantaan tai generoida SQL -koodi, joka voidaan ajaa

erikseen tietokantapalvelimella, mikäli skeemaan halutaan vielä tehdä muutok-

sia.

• Update, käytetään olemassa olevan skeeman päivittämiseen. Päivittää skeeman

suoraan tietokantapalvelimelle tai generoi muutoksia varten tarvittavan SQL -

koodin.

• Drop, toimii kuten SQL DROP -komento eli hävittää tietokannan.

3.9.4 Orm:schema-validate

Schema-validate työkalulla voidaan tarkistaa mappaustietojen oikeellisuus. Validointi-

työkalu ilmoittaa kaikista havaitsemistaan virheistä ja puutteista. Validointi on hyvä

tehdä komentorivityökalulla jo kehitysvaiheessa, koska Doctrinesta puuttuu joitakin

ajon aikaisia tarkistuksia, joten virheellisetkin mappaustiedot saattavat toimia, ainakin

siihen asti, kunnes virheeseen törmätään ajon aikana.

Page 30: DOCTRINE 2 ORM JA ZEND FRAMEWORK 2 SOVELLUKSEN … · 2018. 10. 2. · Doctrine 2 ORM and Zend 2 Framework in Further Development of a Software Appli-cation . Case: Travel Expense

30

4 ORM:N HYÖDYT JA HAITAT

4.1 Hyödyt

Seuraavassa on lueteltu joitakin ORM tuotteen käytöstä havaitsemiani hyötyjä.

4.1.1 Ajan säästäminen ja turhan työn välttäminen

Orm -tuotetta käyttämällä voidaan saavuttaa kehitystyössä säästöjä työmäärää pienen-

tämällä. Rahallisten ja ajallisten säästöjen lisäksi voidaan myös ajatella, että työaika,

joka säästyy toistuvien CRUD (Create Read Update Delete) operaatioiden kirjoittami-

selta, voidaan sijoittaa laadukkaamman businesslogiikan kirjoittamiseen. (Block 2006.)

Koodiesimerkissä 9. havainnollistuu työajan säästö ja turhan työn välttäminen melko

hyvin.

KOODIESIMERKKI 9. Ajoneuvon tietojen tallentaminen tietokantaan, vasemmalla

perinteinen tapa ja oikealla puolella Doctrine 2 ORM.

Page 31: DOCTRINE 2 ORM JA ZEND FRAMEWORK 2 SOVELLUKSEN … · 2018. 10. 2. · Doctrine 2 ORM and Zend 2 Framework in Further Development of a Software Appli-cation . Case: Travel Expense

31

Koodiesimerkissä 9. tehdään ajoneuvon ja ajoneuvon moottorin tallentaminen tietokan-

taan. Doctrine 2:lla tehty tallennus vie rivimääräisesti alle puolet siitä, mitä perinteiseen

tapaan tehty tallennus. Tässä on kyseessä erittäin yksinkertainen esimerkki. Mitä isom-

pia ja monimutkaisempia tallennuksia ja hakuja tehdään, sitä selvemmin ORM -tuote

tekee eroa perinteiseen tapaan.

4.1.2 Ylläpidettävyyden helpottuminen

Tietokantaan tehtävät muutokset heijastuvat koodiin vain mappaustietoihin, joten enää

ei ole tarvetta muuttaa lukuisia määriä kyselyitä. Oliot käyttävät automaattisesti muut-

tuneita mappaustietoja operaatioiden suorittamisessa.

4.1.3 Tietokantariippumattomuus

Sama koodi toimii useammilla tietokantatuotteilla, ei tarvetta kirjoittaa tuotespesifistä

koodia.

4.2 Haitat

Seuraavassa on listattuna joitakin itse havaitsemiani sekä yleisesti mainittuja ORM -

tuotteen käytöstä aiheutuvia kielteisiä seikkoja.

4.2.1 Liika abstraktio

ORM -tuotteet abstrahoivat tietokannan pois näkyvistä. Tämä on toisaalta haluttu omi-

naisuus, mutta saattaa myös hankaloittaa asioiden syvällisempää ymmärtämistä, ongel-

matilanteissa ei enää voida helposti nähdä mikä ohjelmassa on vialla jos ei se toimi.

Esimerkiksi Doctrine 2 heittää virhetilanteessa poikkeuksen, jonka perimmäisen syyn

selvittäminen voi hetkittäin olla työn ja tuskan takana. Perinteisellä tavalla tehty SQL -

kielinen kysely taas voitaisiin nopeasti testata kokeilemalla sitä suoraan tietokantaan ja

virheen syy paljastuisi melko nopeasti.

4.2.2 Virheen etsinnän vaikeutuminen

Page 32: DOCTRINE 2 ORM JA ZEND FRAMEWORK 2 SOVELLUKSEN … · 2018. 10. 2. · Doctrine 2 ORM and Zend 2 Framework in Further Development of a Software Appli-cation . Case: Travel Expense

32

Virheen etsiminen ORM -tuotteella tehdystä koodista voi olla todella haastavaa, koska

debug -tietoa on tarjolla vähintäänkin riittävästi. Perinteisestä SQL kyselystä on yleensä

aika helppo sanoa, että mikä siinä on vialla. Toisin on ORM tuotteen kanssa.

Esimerkiksi Doctrine 2 saattaa tulostaa debug -tietoa minuuttitolkulla selaimen ikku-

naan, jos otetaan vähänkään summittaisempi lähestymistapa siihen, että mitä tietoja tu-

lostetaan. Toki tähän voidaan itse vaikuttaa, mutta perinteisiin var_dump() komentoihin

ei Doctrine 2:n kanssa kannata turvautua.

4.2.3 Suorituskykyyn liittyvät asiat

ORM -tuotteiden käyttöön saattaa liittyä suorituskykyongelmia. Yleisimmät suoritusky-

kyyn liittyvät ongelmat ovat:

• Suuri muistin käyttö

• Hitaus

Suuri muistin käyttö liittyy usein siihen, ettei tuotteen ominaisuuksia täysin käytetä hy-

väksi, esimerkkinä tilanne, jossa luetaan taulukkoon olioita silmukassa. Jokaisessa

haussa haetaan yksi olio, jolla on mapattuna assosiaatio toiseen olioon. Eli nyt tämänkin

olion tiedot haetaan ja suoritetaan vielä hydraatio-operaatio, joka myöskin on melko

raskas operaatio suorituskyvyn kannalta.

Lopulta on kasassa suunnaton määrä olioita, joita ei kaikkia välttämättä tarvita suorituk-

sen aikana. Näiden ylimääräisten tietojen lataaminen ja ylimääräisten hydraatio-

operaatioiden suorittaminen on usein estettävissä, pitää vain tietää miten se tehdään.

Hitaus voi liittyä samaan asiaan, em. esimerkissä saattaa muodostua tilanne, jossa tieto-

kantaa kuormitetaan kysely kerrallaan ja yhteys tukehtuu.

Page 33: DOCTRINE 2 ORM JA ZEND FRAMEWORK 2 SOVELLUKSEN … · 2018. 10. 2. · Doctrine 2 ORM and Zend 2 Framework in Further Development of a Software Appli-cation . Case: Travel Expense

33

5 ZEND FRAMEWORK 2

5.1 Yleistä sovelluskehyksistä

Sovelluskehyksien käytölle on lukuisia syitä. Keskeisimmät syyt liittyvät seuraaviin

seikkoihin: (Abeysinghe 2009, 46–48.)

• Sovelluskehys ohjaa hyvien käytäntöjen (best practices) ja suunnittelumallien

(design patterns) noudattamiseen.

• Sovelluskehys helpottaa kehittämistyötä, koska se usein sisältää yleiskäyttöisiä

osia valmiina, kehittäjä voi näin ollen keskittyä juuri oman projektinsa kannalta

tärkeisiin asioihin.

• Yleiskäyttöiset osat ovat valmiiksi testattuja.

• Sovelluskehys tarjoaa rungon, jonka mukaan toimitaan, esimerkiksi Zend Fra-

mework 2 skeleton project, jossa on valmiina hakemistorakenne, joihin ohjel-

massa mukana olevat tiedostot tulisi sijoittaa.

• Sovelluskehykset poistavat kehitystyöstä turhaa monimutkaisuutta.

• Edellä mainituista syistä johtuen sovelluskehyksen käyttäminen säästää aikaa ja

rahaa

5.2 MVC-suunnittelumalli

MVC eli Model-View-Controller -suunnittelumallin tarkoituksena on ohjata kehitystyö-

tä siten, että käyttöliittymä, logiikka ja data ovat toisistaan eriytettyjä. (Abeysinghe

2009, 31)

Käytännössä tämä tarkoittaa sitä, että käyttöliittymäosaan (View) liittyvää koodia ei

pitäisi löytyä ohjelmalogiikan sisältävän ohjainosan (Controller) koodin seasta, eikä

kumpaankaan edellä mainittuun liittyvää koodia pitäisi löytyä malliosaan (Model) liit-

tyvän koodin seasta. Tätä eriyttämistä kutsutaan nimellä Separation Of Concerns (Haas-

teiden eriyttäminen). (Abeysinghe 2009, 33.)

Korkean tason käsitteenä MVC-suunnittelumalli tarkoittaa sitä, että ohjelman rakenne

jaetaan kolmeen osaan seuraavan kaltaisesti: (Freeman 2013, 51.)

Page 34: DOCTRINE 2 ORM JA ZEND FRAMEWORK 2 SOVELLUKSEN … · 2018. 10. 2. · Doctrine 2 ORM and Zend 2 Framework in Further Development of a Software Appli-cation . Case: Travel Expense

34

• Model eli malliosa, jossa esitetään joko näkymällä tarvittava tieto, jota käsitel-

lään näkymien ja ohjaimen välillä tai vaihtoehtoisesti ns. domain-malli, jossa

esitetään sovelluksen käsittelemä tieto ja sen käsittelysäännöt.

• View eli näkymäosa. Näkymäosassa esitetään malliosan tiedot käyttäjälle

• Controller eli ohjainosa, jossa tehdään operaatioita näkymään ja malliin. Yleensä

tiedon käsittelyyn liittyvät osat, ns. businesslogiikka tulisi sijoittaa ohjainosan

koodiin.

Syitä sille, miksi MVC-mallissa eri osat erotetaan toisistaan, on monia. Ensinnäkin,

vaikka kaiken ohjelmaan liittyvän toiminnallisuuden ohjelmoiminen yhteen pakettiin

saattaa tuntua yksinkertaiselta ja alkuun ehkä säästää aikaakin, niin kokonaisuuden kas-

vaessa ohjelman eri osiin tulevien muutoksien hallinnasta muodostuu väkisinkin melko

haasteellista.

Eriyttämällä ohjelman osat toisistaan voidaan tehdä muutoksia eri osiin siten, että muu-

tokset yhteen osaan eivät parhaassa tapauksessa vaadi muutoksia muihin osiin ollenkaan

tai ainakin vaaditut muutokset ovat pieniä.

Toiseksi, eri osiin vaaditaan useammin muutoksia kuin toisiin. Esimerkiksi käyttöliit-

tymään tai businesslogiikkaan voi tulla useinkin muutoksia, kun taas datamalli usein

pysyy samanlaisena pitkiäkin aikoja.

Kolmanneksi, samaan datamalliin voidaan tehdä erilaisia näkymiä eli samaa mallia voi-

daan käyttää useammassa kohdassa ohjelmaa.

Page 35: DOCTRINE 2 ORM JA ZEND FRAMEWORK 2 SOVELLUKSEN … · 2018. 10. 2. · Doctrine 2 ORM and Zend 2 Framework in Further Development of a Software Appli-cation . Case: Travel Expense

35

Malli

Näkymä Kontrolleri

Käyttäjä

ManipuloiPäivittää

Näyttää Käyttää

Manipuloi

KUVA 7. Kaaviokuva MVC -suunnittelumallin toimintaperiaatteesta

5.3 Zend Framework 2:n esittely

Zend Framework 2 (Tästä eteenpäin ZF2) on avoimen lähdekoodin (New BSD lisenssi)

sovelluskehys web-sovellusten ja palveluiden tekemiseen. Se on kehitetty täysin olio-

ohjelmoinnin periaattein ja tukee PHP versioita versiosta 5.3 eteenpäin. ZF2 on asennet-

tavissa Composer -riippuvuuksienhallinnan kautta. (Zend Framework 2016.)

ZF2:ssa tulee mukana mm. komponentit MVC -toteutuksia varten, tietokanta-

abstraktiokerros, lomake-, validointi- sekä autentikointikomponentit. ZF2:n komponent-

teja voi käyttää myös irrallaan sovelluskehyksestä, koska suunnittelussa on keskitytty

siihen, että komponenttien välillä olisi vain vähän tai ei ollenkaan keskinäisiä riippu-

vuuksia. Tehokkaimmillaan ne ovat kuitenkin yhdessä käytettyinä. (Zend Framework

2016.)

Composerin avulla voi asentaa ZF2 projektirungon, jonka päälle voi lähteä rakentamaan

omaa projektiansa. Kuvassa 8. on esitetty ZF2 projektin suositeltu oletusrakenne.

Page 36: DOCTRINE 2 ORM JA ZEND FRAMEWORK 2 SOVELLUKSEN … · 2018. 10. 2. · Doctrine 2 ORM and Zend 2 Framework in Further Development of a Software Appli-cation . Case: Travel Expense

36

KUVA 8. ZF2 skeleton project, ZF2 projektin oletusrakenne.

5.4 Zend Framework 2:n moduuli

ZF2 sovelluskehityksessä perusyksikkönä toimivat module alihakemistosta löytyvät

sovellusmoduulit. Moduuli on siirrettävissä oleva, uudelleen käytettävissä oleva sekä

muihin moduuleihin liitettävissä oleva sovelluskomponentti. Moduuleja yhdistelemällä

on mahdollista rakentaa suurempia ja monimutkaisempia kokonaisuuksia. (Shasankar

2013, 27.)

ZF2 moduulien keskeisinä etuina mainitaan seuraavat asiat: (Shasankar 2013, 27.)

• Itsenäinen kokonaisuus, siirrettävissä oleva, uudelleenkäytettävissä

• Riippuvuuksien hallinta

• Kevyt ja nopea

• Tukee Phar -pakkauksia ja Pyrus -distribuutioita

ZF2 tarjoaa myös moduuleille valmiin perusrungon josta kehittäjä voi lähteä rakenta-

maan sovellusta. Skeleton moduulin saa kloonattua itselleen ajamalla seuraavan ko-

mennon projektin module alihakemistossa:

git clone git://github.com/zendframework//ZendSkeletonModule.git <appName >.

5.5 MVC -malli ja Zend Framework 2

Page 37: DOCTRINE 2 ORM JA ZEND FRAMEWORK 2 SOVELLUKSEN … · 2018. 10. 2. · Doctrine 2 ORM and Zend 2 Framework in Further Development of a Software Appli-cation . Case: Travel Expense

37

ZF2 MVC -toteutus voidaan rakentaa kokonaan mukana tulevia komponentteja käyttäen

tai siihen voidaan ottaa mukaan ulkoisia komponentteja. FZ2 MVC -toteutuksen perus-

osat ovat:

• Controller: Periytetään jommasta kummasta luokasta:

o Zend\Mvc\Controller\AbstractActionController

o Zend\Mvc\Controller\AbstractRestfulController.

• Model: ZF2 tarjoaa malliluokkien käyttöön TableGateway luokan palvelut,

TableGateway voidaan kuitenkin korvata myös ORM tuotteella.

• View: ZF2 näkymiä luotaessa käytetään .phtml päätteisiä tiedostoja. Nämä tie-

dostot ovat käytännössä HTML koodia, jonka sekaan upotetaan PHP koodin

pätkiä.

• Forms: ZF2 formit ovat komponentteja, joiden avulla voidaan tehdä lomakkeita.

Page 38: DOCTRINE 2 ORM JA ZEND FRAMEWORK 2 SOVELLUKSEN … · 2018. 10. 2. · Doctrine 2 ORM and Zend 2 Framework in Further Development of a Software Appli-cation . Case: Travel Expense

38

6 ASIAKKAAN ONGELMA

6.1 Asiakkaan X toiminnanohjausjärjestelmä

Evolvit Oy:n asiakkaalla X on käytössään toiminnanohjausjärjestelmä, joka on toteutet-

tu PHP ohjelmointikielellä. Toiminnanohjausjärjestelmä on siirtynyt Evolvit Oy:lle yl-

läpitoon ja jatkokehitykseen vuoden 2015 alussa. Tietokantana järjestelmässä käytetään

MySQL -tietokantaa. Toiminnanohjausjärjestelmää on kehitetty pitkään ja kehitystyön

saatossa siihen on luotu erittäin paljon ominaisuuksia. Toiminnanohjausjärjestelmän

perustehtävänä asiakkaan X käytössä on tukea liiketoimintaa tarjoamalla palvelut yri-

tyksen työntekijöiden asiakaskäyntien varaamiseen ja asiakaskäynneistä aiheutuneiden

palkka sekä kilometrikorvausten toimittamiseksi palkanmaksuun.

Asiakkaan X toiminnanohjausjärjestelmässä on ilmennyt kilometrilaskentaan liittyvä

vika, joka tulisi korjata. Samalla matkalaskujen sekä työntekijöiden menekinedistys-

työstä kirjattavien raporttien syöttölomakkeet tulisi uudistaa siten, että matkalaskuja

olisi mahdollista syöttää myös mobiililaitteilla.

6.2 Järjestelmän nykytila

Järjestelmän nykytilasta yleisesti voidaan todeta, että sen keskeiset ominaisuudet toimi-

vat varsin hyvin. Jotkin ominaisuudet taas ovat olemassa, mutta näyttävät keskeneräisil-

tä tai eivät toimi ollenkaan.

6.2.1 Ohjelmakoodi

Järjestelmää on kehitetty jo pitkän aikaa ja se näyttäytyy monenkirjavina ratkaisuina

toteutuksessa sekä koodin suurena määränä. Ohjelmakoodi on jaettu luokkiin, mutta

oikeastaan näitä luokkia käytetään vain nimiavaruuksina, käytännössä lähestulkoon

kaikki luokat kutsuvat vain omia funktioitansa. Joitakin poikkeuksia löytyy, mutta täl-

löinkin käytetään vain staattisia funktiokutsuja, olioita luokista ei juurikaan instantioida.

Page 39: DOCTRINE 2 ORM JA ZEND FRAMEWORK 2 SOVELLUKSEN … · 2018. 10. 2. · Doctrine 2 ORM and Zend 2 Framework in Further Development of a Software Appli-cation . Case: Travel Expense

39

Näkymiä ja ohjelmalogiikkaa ei ole erotettu toisistaan, eikä käytössä ole myöskään mal-

liluokkia tietokantayhteyksiä varten. Ohjelmakoodi on näin ollen erittäin sekavaa ja

vaikeaa ylläpitää.

Nykytilassa järjestelmän näkymät on toteutettu siten, että eri toiminnoille on toteutettu

saman sisältöisiä näkymiä, vaikka toiminnallisuuksissa olisi vain vähäisiä eroavavai-

suuksia. Esimerkkinä voidaan ottaa vaikkapa matkalaskunäkymä: sama toiminto on

järjestelmässä toteutettu eri paikkoihin, ylläpitäjän matkalaskun korjausnäkymä, edusta-

jan matkalaskunäkymä, työntekijän matkalaskunäkymä jne.

Nämä kaikki näkymät ovat saman sisältöisiä, ne eroavat toisistaan lähinnä tallennuslo-

giikaltansa. Kaikki nämä näkymät olisi mahdollista toteuttaa siten, että käytettäisiin

samaa näkymää ja vain logiikka muuttuu käyttökontekstin mukaan. Tämä helpottaisi

ylläpidettävyyttä huomattavasti, koska kaikki muutokset näkymään tarvitsisi muutostöi-

den jälkeen tehdä vain yhteen paikkaan, eikä muutoksia varten tarvitsisi enää etsiä koo-

dia monesta eri paikasta.

6.2.2 Tietokanta

Järjestelmän taustalla oleva tietokanta sisältää 260 taulua. Tietokantamoottorina käyte-

tään MyISAM:ia muutamaa poikkeusta lukuun ottamatta. Tämä aiheuttaa sen, ettei tie-

tokantaoperaatioita voida ajaa transaktioissa, vaan ne suoritetaan operaatio kerrallaan,

eivätkä rollback -operaatiot ole mahdollisia.

Tietokannan taulujen välisiin yhteyksiin ei ole määritelty viite-eheysrajoitteita, yhteydet

hoidetaan vain viittaamalla toisen taulun pääavaimeen. Taulujen ja ”vierasavainten”

nimeämiskäytännöt ovat sekavia, eikä samoja nimiä ole käytetty yhtenäisesti eri pai-

koissa, mikä voi hetkittäin aiheuttaa hämmennystä tehtäessä liitoksia taulujen välille.

Taulujen väliset monen suhde moneen -yhteydet on joissain kohdin hoidettu ilman lii-

tostaulua, erottamalla viiteavaimet pilkulla toisistaan tekstikenttään. Järjestelmän toi-

minnan kannalta huolestuttavimpana kohtana voidaankin pitää juuri tietokannan kehnoa

suunnittelua. Usein tehtäessä järjestelmään uutta toimintoa joudutaan tekemään tieto-

kantaan muutoksia, jotka saattavat rikkoa jo olemassa olevia toimintoja.

Page 40: DOCTRINE 2 ORM JA ZEND FRAMEWORK 2 SOVELLUKSEN … · 2018. 10. 2. · Doctrine 2 ORM and Zend 2 Framework in Further Development of a Software Appli-cation . Case: Travel Expense

40

6.3 Kilometrikorvausten laskennassa ilmennyt vika

Yrityksen työntekijöille maksetaan kilometrikorvauksia työpäivän aikana tapahtuneesta

matkustamisesta. Työntekijä täyttää työpäivän aikana tekemistään työsuoritteista rapor-

tin. Raportti kohdistuu aina jollekin myymälälle sekä projektille. Työntekijän on mah-

dollista tehdä myymälässä käydessään työsuoritteita useille projekteille.

Kilometrikorvauksia laskettaessa järjestelmän pitäisi nykytilassaan toimia seuraavalla

tavalla:

1. Työntekijä valitsee matkalaskut osion

2. Järjestelmä hakee tehdyt työpäivät ja ehdottaa työntekijälle mahdollisia päiviä,

joille matkalasku voitaisiin tehdä

3. Työntekijä valitsee mille päivälle matkalasku tehdään

4. Järjestelmä hakee kyseisen päivän käydyt myymälät ja esittää ne näkymässä

a. Ensimmäisenä ja viimeisenä paikkana näkyy työntekijän kotiosoite

5. Työntekijä voi vielä tässä vaiheessa lisätä ensimmäisen ja viimeisen paikan vä-

liin pysähdyksiä

6. Kun kaikki pysähdykset ovat näkymässä, työntekijä painaa ”laske kilometrit”

painiketta, joka hakee reitin kilometrit käyttäen Google Mapsin tarjoamaa raja-

pintaa

7. Käyttäjä painaa ”Tallenna matkalasku” painiketta

8. Matkalasku tallennetaan tietokantaan tilassa hyväksymätön

9. Esimies valitsee matkalaskun ja hyväksyy sen

10. Tallennus käynnistyy

a. Tässä vaiheessa haetaan käytyihin myymälöihin kohdistuvat projektit,

jotta matkalaskut voidaan jakaa projektin tilaajien kesken

b. Kilometrit jaetaan projektien kesken

c. Muodostetaan matkalaskukirjaus palkkoihin projekteittain

d. Tallennetaan palkkarivi tai rivit, jos projekteja oli useampia

Kilometrikorvausten tallennuksessa on kuitenkin vika, josta aiheutuu kilometrikorvaus-

ten kohdentuminen väärille projekteille. Vika johtuu siitä, ettei tietoja voida tietokannan

huonon suunnittelun takia liittää toisiinsa luonnollisesti, vaan kilometrien kohdentumi-

nen projekteille koitetaan kunnollisten viiteavainten ja liitostaulujen puuttuessa ikään

Page 41: DOCTRINE 2 ORM JA ZEND FRAMEWORK 2 SOVELLUKSEN … · 2018. 10. 2. · Doctrine 2 ORM and Zend 2 Framework in Further Development of a Software Appli-cation . Case: Travel Expense

41

kuin arvata. Kuvassa 9. on esitetty kohdealue sellaisena kuin se esiintyy tietokannassa

tällä hetkellä.

KUVA 9. Matkalaskun laskentaan liittyvät keskeisimmät taulut.

Kuvasta 9. voidaan nähdä, että taulut mm_matkalasku ja mm_matkalasku_pysähdys

ovat ikään kuin irrallaan muusta raportointikokonaisuudesta. Matkalaskuun kuuluvan

pysähdyksen projektia yritetään hakea tietokannasta päivämäärän ja myymälän perus-

teella, mutta tämä ei anna luotettavia tuloksia.

6.4 Kilometrikorvauksien laskennan korjaaminen

Korjausten perustana tietokantaan tulee luoda yhteys taulujen projektit ja

mm_matkalasku_pysähdys välille. Kuvassa 10. on esitetty korjattu toimintamalli, jolla

tiedot saadaan liitettyä toisiinsa luotettavasti.

Page 42: DOCTRINE 2 ORM JA ZEND FRAMEWORK 2 SOVELLUKSEN … · 2018. 10. 2. · Doctrine 2 ORM and Zend 2 Framework in Further Development of a Software Appli-cation . Case: Travel Expense

42

KUVA 10. Korjattu tietokantakuvaus: linkitystä varten on lisätty taulu monen suhde

moneen yhteyttä varten.

Uusi korjattu malli sallii järjestelmän toimia siten, että samalle pysähdykselle voidaan

kirjata useammalle projektille kuuluvia töitä. Samalla saadaan tietokantaan kirjattua

palkkakirjausten laskentaa varten varma tieto siitä, mille projekteille matkalaskun kilo-

metrit jakaantuvat.

Myös matkalaskun kirjaamisen logiikkaan tulee uuden tietokantamallin käyttöönoton

myötä muutos. Nykytilassa matkalasku kirjattaan järjestelmään vasta siinä vaiheessa,

kun työntekijä tekee matkalaskun. Korjausten jälkeen matkalasku kirjataan tietokantaan

heti ensimmäisestä työpäivän aikana tapahtuneesta pysähdyksestä. Työntekijälle voi siis

muodostua tietokantaan useita avonaisessa tilassa olevia matkalaskuja samanaikaisesti.

Halutessaan työntekijä voi käydä jättämässä matkalaskun hyväksyttäväksi esimiehelle

valitsemalla avoimista matkalaskuistansa matkalaskun, jonka haluaa hyväksyttäväksi.

Avoimena olevaa matkalaskua on mahdollista myös muokata eli matkalaskulle voidaan

lisätä tai poistaa pysähdyspaikkoja.

Page 43: DOCTRINE 2 ORM JA ZEND FRAMEWORK 2 SOVELLUKSEN … · 2018. 10. 2. · Doctrine 2 ORM and Zend 2 Framework in Further Development of a Software Appli-cation . Case: Travel Expense

43

Kun matkalaskuihin kohdistuvat pysähdykset ja pysähdyksiin kohdistuvat projektit ovat

tietokannassa tallennettuna luotettavasti, matkalaskun laskennan toteuttaminen on lä-

hinnä triviaali toimenpide, jossa kerätään kilometrit projekteittain ja kirjataan palkkoi-

hin kulut projekteittain palkkariveiksi.

Matkalaskennan muutokset koskevat siis myös päivän aikana täytettäviä työraportteja

tai lähinnä niiden tallennuslogiikkaa. Näin ollen onkin järkevää tehdä näihin molempiin

osioihin kohdistuvat muutokset samaan aikaan.

Uudistustöissä käytettäviksi työkaluiksi valikoituivat Zend Framework 2 ja Doctrine 2

siitä syystä, että asiakkaan X järjestelmään on jo toteutettu näillä tekniikoilla toisenlai-

seen työhön kohdistuvien raporttien uudistaminen mobiiliystävällisemmiksi. Osaa jo

aiemmin tehdyistä Doctrine 2:n käyttämistä malliluokista voidaan uudelleen käyttää nyt

tehtävissä muutostöissä. Käyttöliittymien syöttölomakkeiden toteutuksessa tullaan käyt-

tämään Twitterin tarjoamaa Bootstrap -kirjastoa. Bootstrap antaa työkalut responsiivis-

ten käyttöliittymien tekemiseksi ja iso osa tyyleistä, joita uudistuksen aikana tullaan

tarvitsemaan, on jo valmiiksi määritelty aiemmassa uudistusprojektissa.

6.5 Muutostöiden toteuttaminen

6.5.1 Tietokanta ja entiteetit

Muutostöiden ensimmäisenä vaiheena korjataan tietokannan rakenne vastaamaan tal-

lennustarpeita. Samalla tietokannasta siivotaan pois rivejä, joiden viiteavaimet eivät

enää viittaa minnekään. Tyhjistä viittauksista aiheutuu ongelmia Doctrine 2:n kanssa,

jos koetetaan hakea tietokannasta rivejä, joita siellä ei enää ole, varsinkin, jos haettavat

rivimäärät ovat kovin suuria.

Kun tietokanta on saatu kuntoon, voidaan Doctrine 2:n komentorivityökaluilla tarkistaa

skeeman oikeellisuus ja luoda entiteettiluokat kohdealueen tauluista. Entiteettiluokat

tulevat tarvitsemaan jonkin verran käsityötä, jotta liitokset saadaan toimimaan oikein.

6.5.2 Tiedon validointi

Page 44: DOCTRINE 2 ORM JA ZEND FRAMEWORK 2 SOVELLUKSEN … · 2018. 10. 2. · Doctrine 2 ORM and Zend 2 Framework in Further Development of a Software Appli-cation . Case: Travel Expense

44

Entiteettiluokkiin tullaan toteuttamaan myös syötetyn datan validointi. Tällä hetkellä

käyttäjän syötteitä ei lomakkeilla tarkasteta ollenkaan, vaan tiedot syötetään sellaise-

naan suoraan tietokantaan. Tämä malli mahdollistaa virheellisen tiedon syöttämisen,

mutta on myös tietoturvariski, koska sallii ns. SQL -injektoinnin.

Validointi tehdään siten, että entiteettluokat toteuttavat ZF2:n InputAwareInteface raja-

pinnan. Rajapinta vaatii toteutettavaksi kaksi funktiota, setInputFilter sekä getInputFil-

ter. Koodiesimerkissä 10. on kuvattu entiteettiluokassa toteutettu validointi, jossa käyte-

tään ZF2 InputFilteriä.

KOODIESIMERKKI 10. Attribuuttien validointi InputFilterin avulla.

Koodiesimerkissä 10. on esitetty yksinkertainen esimerkki InputFilterin toiminnasta.

Tässä esimerkissä luodaan ensin InputFactory, jonka avulla voidaan luoda InputFilter.

Tämän jälkeen tehdään taulukko, jossa on määritelty suodattimet, joilla syötteiden oi-

keellisuus tarkistetaan. Ensimmäinen suodatin tarkistaa seuraavat asiat kentälle id:

1. Että kentän arvo on syötetty, koska arvo vaaditaan esiintyväksi syötteissä

2. Syötteen tulee olla kokonaislukutyyppinen

Page 45: DOCTRINE 2 ORM JA ZEND FRAMEWORK 2 SOVELLUKSEN … · 2018. 10. 2. · Doctrine 2 ORM and Zend 2 Framework in Further Development of a Software Appli-cation . Case: Travel Expense

45

3. Syötteen pienin sallittu arvo on 1

Toinen suodatin tarkastaa kentän kommentti oikeellisuuden:

1. Syötteestä karsitaan ensin pois html sisältö sekä turhat välilyönnit käyttäen

StripTags ja StringTrim suodattimia

2. Sen jälkeen tarkastetaan kentän pituus:

a. Syötteen tulee olla enkoodaukseltansa muotoa UTF-8

b. Syötteen maksimipituus on 2000 merkkiä, näin voidaan rajoittaa syötteen

pituus samaksi kuin mitä tietokannassa kentän sallittu maksimi on.

Kun suodattimet on määritetty, luodaan InputFilter -olio aiemmin luodun InputFactoryn

avulla. InputFactorylle annetaan parametrina suodattimet. InputFilter -olion luonnin

jälkeen voidaan palauttaa se kontrollerin käytettäväksi.

Validoinnin toteuttaminen entiteettiluokassa on myös siinä mielessä hyvä ratkaisu, että

kun se on kerran toteutettu, sitä voidaan käyttää uudelleen, mikäli entiteettiä käytetään

jossain toisessa yhteydessä.

Validointia tehdään kuitenkin myös kontrollerissa ja joissain tapauksissa on järkevää

tehdä sitä myös näkymässä. Näkymällä voidaan esimerkiksi ottaa välittömästi kiinni

käyttäjän ilmeisen virheellisiä syötteitä tai puuttuvia kenttiä, ennen kuin niitä lähetetään

eteenpäin käsiteltäväksi. Näin säästetään aikaa ja serverin kapasiteettia: sivua ei lähetetä

kontrollerin tai entiteetin tarkastettavaksi virheellisenä, koska jos virhe otettaisiin kiinni

vasta lähetyksen jälkeen, järjestelmän tulisi kuitenkin palauttaa käyttäjä virheellisenä

syötetylle lomakkeelle. Pahimmassa tapauksessa lomakkeen sisältöä pitäisi hakea uu-

delleen näkymälle, joka olisi totaalista resurssien haaskaamista.

6.5.3 Näkymät

Nykyiset näkymät tullaan korvaamaan ZF2:n näkymillä. FZ2:ssa näkymät muodoste-

taan siten, että kontrollerissa määritetään toimintoja (actions), jotka palauttavat näky-

män. Näkymänä käytetään ViewModel luokan ilmentymää.

Näkymälle voidaan antaa sitä kontrollerissa luotaessa muuttujia, joita voidaan tämän

jälkeen käyttää suoraan näkymällä. Itse näkymä, kuten aiemmin todettiin, tehdään erilli-

Page 46: DOCTRINE 2 ORM JA ZEND FRAMEWORK 2 SOVELLUKSEN … · 2018. 10. 2. · Doctrine 2 ORM and Zend 2 Framework in Further Development of a Software Appli-cation . Case: Travel Expense

46

seen .phtml päätteiseen tiedostoon, johon voidaan kirjoittaa html koodin sekaan php

elementtejä. Muuttujana voidaan antaa myös kokonaisia käyttöliittymäkomponentteja,

kuten lomake eli Form.

Form on ZF2 komponentti, joka voidaan antaa näkymälle, jonka perusteella näkymällä

voidaan tehdä määrittelyjen perusteella lomake. Lomakkeen kentät voidaan määritellä

suoraan lomakkeen luovan luokan konstruktoriin tai ne voidaan antaa lomakkeelle eril-

lisinä Fieldset luokan ilmentyminä. Nyt tehtävissä muutostöissä kaikki lomakkeet tul-

laan tekemään niin pitkälle kuin mahdollista juuri Fieldsettien avulla. Tämän menetel-

män etuna on se, että näin voidaan määritellä lomakkeille valmiita kenttäjoukkoja, joita

voidaan tarpeen mukaan käyttää monessa paikassa. Esimerkkinä voidaan ottaa vaikkapa

matkalaskentaan liittyvät kentät. Kentät joita matkalaskentaan laskentaan tarvitaan,

ovat:

• Aloituspäivä

• Aloituskellonaika

• Ensimmäinen reittipiste

• Viimeinen reittipiste

• Painikkeet reittipisteiden lisäämiseksi ja poistamiseksi

• Matkan lopettamisvuorokausi

• Matkan lopettamiskellonaika

Tämän listan matkustusaikoja koskevista tiedoista on mahdollista tehdä Formille annet-

tava Fieldset. Fieldsetille on mahdollista määritellä kenttien tiedot. Koodiesimerkissä

11. on havainnollistettu fieldsetin toimintaa.

Page 47: DOCTRINE 2 ORM JA ZEND FRAMEWORK 2 SOVELLUKSEN … · 2018. 10. 2. · Doctrine 2 ORM and Zend 2 Framework in Further Development of a Software Appli-cation . Case: Travel Expense

47

KOODIESIMERKKI 11. Fieldsetin käyttö.

Koodiesimerkissä 11. määritellään luokan konstruktorissa Fieldsetin sisältämät kentät.

Esimerkissä näkyvissä matkan aloitusajankohdan sisältävät kentät. Kentän nimi määrit-

tää näkymällä käytettävän html -tagin name -attribuutin arvon. Tyypillä määritetään

kentän tyyppi eli miten kenttä esitetään näkymällä. Optioina kummallekin määritellylle

kentälle annetaan otsikko, päivämääräkentälle päivämäärän esitystavan muoto, tuntiken-

tälle taas annetaan optiona vuorokauden tunnit. Attribuutteina annetaan päivämääräken-

tälle required eli vaadittu kenttä ja tuntikentälle attribuutti class, jolla voidaan jo tässä

vaiheessa määritellä kentän käyttämä css muotoilu.

Kun Fieldset on määritelty, sitä voidaan käyttää lomakkeella koodiesimerkin 12. tapaan.

KOODIESIMERKKI 12. Fieldsetin käyttäminen lomakkeella.

Koodiesimerkissä 12. havainnollistuu Fieldsetin käyttämisestä saatava hyöty: Samalla

lomakkeella käytetään kahdesti samaa Fieldsettiä eli säästytään ylimääräiseltä työltä.

Page 48: DOCTRINE 2 ORM JA ZEND FRAMEWORK 2 SOVELLUKSEN … · 2018. 10. 2. · Doctrine 2 ORM and Zend 2 Framework in Further Development of a Software Appli-cation . Case: Travel Expense

48

Edellä luotu Form -komponentti Fieldsetteineen voidaan luoda kontrollerissa, josta se

voidaan antaa näkymäkomponentille. Näkymän tulostavalla .phtml tiedostolla lomake

voidaan tulostaa php:n echo komentoa käyttäen.

6.5.4 Kontrollerit

Muutostöiden toteutuksen tuloksena sovellukseen tehdään kaksi kontrolleria. Toinen

kontrollereista huolehtii menekinedistystyön raportoinnin tarpeista ja toinen matkalas-

kuraportoinnin tarpeista. Muutostöissä toteutettavat luokat tullaan periyttämään Abst-

ractActionController luokasta. AbstractActionController luokasta periytetyissä luokissa

toteutetaan actioneiksi kutsuttuja funktioita, jotka palauttavat näkymiä. Actioneissa to-

teutetaan suurin osa sovelluksen businesslogiikasta sekä valmistellaan näkymille annet-

tavat komponentit.

Nämä actionit täytyy lisätä moduulin konfiguraatiotiedostoon, jonka jälkeen actionin

toiminnallisuutta voidaan kutsua ohjaamalla liikenne konfiguroituun osoitteeseen, esi-

mekrkiksi matkalaskua voitaisiin hakea osoitteella http://mysite.com/matkalasku/123.

Edellä esitetty url palauttaisi matkalaskun jonka id kentän arvo on 123.

Käyttämällä edellä kuvatun kaltaista ohjausta, voidaan vanha ja uusi puoli sovelluksesta

yhdistää. Vanhalla puolella sovellusta on olemassa varsin käyttökelpoiset listanäkymät,

joista voidaan valita täytettäviä raportteja. Jatkossa sovellus vain ohjataan käyttämään

uutta raporttiominaisuutta vanhan sijaan vaihtamalla url -osoitteet.

Matkalaskutoiminnallisuuden toteuttavassa kontrollerissa tullaan käyttämään matkalas-

kentaan IvoryGoogleMapBundle -nimistä kirjastoa, jonka avulla voidaan laskea auto-

maattisesti työntekijän antamien reittipisteiden välinen matka käyttäen Google Mapsin

reittilaskentaa. Tätä kirjastoa on jo testattu ennestään, ja se tuntuu toimivan melko luo-

tettavasti.

Page 49: DOCTRINE 2 ORM JA ZEND FRAMEWORK 2 SOVELLUKSEN … · 2018. 10. 2. · Doctrine 2 ORM and Zend 2 Framework in Further Development of a Software Appli-cation . Case: Travel Expense

49

7 JOHTOPÄÄTÖKSET JA POHDINTA

7.1 Doctrine 2

Doctrine 2 helpottaa omaa työtäni melkoisesti juuri tietokantaan kohdistuvien rutii-

nioperaatioiden vähentymisenä. Toisaalta alkuun tarvitsi panostaa paljon aikaa tuotteen

hahmottamiseen ja käytön opetteluun, sillä ominaisuuksia on todella paljon, pelkästään

manuaali kattaa 370+ sivua. Käytön opiskelua hankaloittaa myös se, ettei aiheesta ole

kirjoitettu paljon kirjoja. Nettilähteitä omatoimiselle opiskelulle löytyy toki runsaasti,

mutta tällöin muodostuu usein pulmaksi tiedon luotettavuus eli onko nettilähteessä neu-

vottu toimintamalli oikeasti parhaiden käytäntöjen mukainen.

Aivan pieniin projekteihin en Doctrine 2:ta lähtisi suosittelemaan työkaluksi, se tuntuisi

hieman yliampuvalta ratkaisulta, jos halutaan kehittää jotain pientä nopeasti. Suurem-

missa projekteissa sen käyttöönotto on mielestäni perusteltua sen takia, että tietokantaan

tulevia muutoksia tarvitsee periaatteessa mallintaa koodissa vain entiteettiluokkiin, jol-

loin säästytään suurelta määrältä työtä.

Otin työkoneellani auki olevasta projektista hieman statistiikkaa, projekti sisältää:

• 4719 INSERT lausetta

• 8507 UPDATE lausetta

• 6583 DELETE lausetta

• 23673 SELECT lausetta

Tällaisten kyselymäärien hallinta tietokantamuutosten kohdalla voi hetkittäin olla melko

haastavaa. Jokaista ei tietenkään tarvitse käydä läpi jonkun asian muuttuessa, mutta jon-

kin verran niitä täytyy aina käydä läpi muutosten ilmaantuessa.

ORM ei ole mikään oikotie onneen, se todellakin tuntuu hetkittäin hidastavan sovelluk-

sen toimintaa ja kuluttaa paljon muistiresursseja. Myös virheiden jäljittäminen voi han-

kaloitua ORM tuotteen käyttöönoton myötä.

Page 50: DOCTRINE 2 ORM JA ZEND FRAMEWORK 2 SOVELLUKSEN … · 2018. 10. 2. · Doctrine 2 ORM and Zend 2 Framework in Further Development of a Software Appli-cation . Case: Travel Expense

50

ORM kuitenkin ohjaa kehitystä ja siinä käytettyjä käytäntöjä yhtenäisempään suuntaan

ja usein myös kannustaa ns. oikeiden toimintatapojen käyttöön. Jo pelkästään siitä syys-

tä olen valmis suosittelemaan sen käyttöä vähänkään isommissa projekteissa, joissa on

monta kehittäjää työskentelemässä samanaikaisesti. Omassa työssäni olen myös havain-

nut, että olemassa olevaan järjestelmään muutoksia tehtäessä jo varsin pienehkön omi-

naisuuden kehittämisen aikana tulevat tietokannan kaikkein keskeisimmät taulut jo mel-

kein väkisin mapatuksi Doctrine 2:ta varten. Näin ollen, kun kehitystyötä jatketaan,

saattaa olla jo paljonkin uudelleen käytettävää koodia olemassa.

7.2 Zend 2 Framework

ZF2 jakaa huomattavasti selkeämmin mielipiteitäni. Sen käyttöönotto projektissa ei ole

mitenkään kovin yksinkertaista ja sen dokumentaatio on paikoitellen melko työlästä

luettavaa. Projektin internetsivustolla on paljon erilaisia tutoriaaleja, mutta tutoriaaleissa

vaikuttaisi olevan melkoisesti virheitä, ainakin siitä päätellen, että käyttäjäkommenteis-

sa valitetaan, ettei koodi toimi, itse en näitä tutoriaaleja ole kovin paljon testaillut.

ZF2 vaatii valtavan määrän konfigurointia, ennen kuin varsinaisesti päästään tekemään

kehitystyötä. Konfiguraatiotiedostoja on myös ripoteltu ikävästi ympäriinsä eli asioita

täytyy pahimmillaan määrittää useisiin paikkoihin. Ajoittain ZF2 tuntuu käyttävän mel-

ko paljon muistia ja toimintojen suorittaminen tuntuu vievän kauan aikaa.

ZF2 on kuitenkin erittäin vakaan oloinen sovelluskehys, se tuntuu toimivan erittäin luo-

tettavasti. Se myös tarjoaa valtavan määrän toiminnallisuuksia sekä melkeinpä pakottaa

käyttämään hyviä toimintatapoja ja kun sen tapaan toimia pääsee sisälle, sen kanssa

työskentely on melko nopeaa.

Opinnäytetyön aiheena olleessa projektissa ZF2 tekee juuri sen mitä tarvitaankin: Sen

avulla voidaan erottaa sovelluksen eri osat MVC mallin mukaisiin osiin ja päästä eroon

moneen paikkaan tehdyistä saman ominaisuuden toteutuksista.

Itse en ZF2:ta suosittelisi aivan pieneen projektiin, sillä sen vaatima konfiguroinnin

määrä on pienen projektin tarpeisiin tarpeettoman suuri.

Page 51: DOCTRINE 2 ORM JA ZEND FRAMEWORK 2 SOVELLUKSEN … · 2018. 10. 2. · Doctrine 2 ORM and Zend 2 Framework in Further Development of a Software Appli-cation . Case: Travel Expense

51

7.3 Pohdintaa

Olisi mielenkiintoista myös testata eri PHP sovelluskehyksiä rinnakkain, jotta voisi saa-

da realistisen kuvan niiden käytön helppoudesta tai vaikeudesta sekä niiden välisistä

suorituskykyeroista. Monista eri lähteistä lukemani perustaalla oletan, että ainakin La-

ravel sekä Symfony 2 olisivat voineet soveltua sovelluskehyksiksi tähän projektiin.

Kummatkin edellä mainituista vaikuttaisivat ainakin pintapuolisen tutustumisen perus-

teella helpommilta oppia kuin ZF2.

Useassa lähteessä mainitaan, että Laravelilla kehitystyö helpottuisi huomattavasti. Mel-

kein yhtä usein kuitenkin mainitaan, että suuremmissa projekteissa ZF2 olisi oikea va-

linta sen takia, että se pakottaa kehittäjät toimimaan tietyn mallin mukaisesti. Tämä on

erittäin kätevää varsinkin, jos projektissa on mukana useita henkilöitä: Kun kaikki toi-

mivat samalla tavalla, on kehittäjien helpompi ymmärtää toistensa kirjoittamaa koodia.

Opinnäytetyön kirjoittamisen aikana ymmärsin monia asioita käsittelyn kohteena olleis-

ta työkaluista, joita en ollut tullut aiemmin ajatelleeksi. Olen myös havainnut, että tä-

män työn kirjoittamisen aikana oppimani asiat ovat jo nyt helpottaneet työtäni muiden

ohjelmistokehysten ja ORM -tuotteiden opiskelussa.

Uskon myös vahvasti, että tämän työn kirjoittamisen aikana opitut asiat tulevat nopeut-

tamaan case esimerkissä käsitellyn tapauksen toteutustöitä merkittävästi.

Page 52: DOCTRINE 2 ORM JA ZEND FRAMEWORK 2 SOVELLUKSEN … · 2018. 10. 2. · Doctrine 2 ORM and Zend 2 Framework in Further Development of a Software Appli-cation . Case: Travel Expense

52

LÄHTEET

Abeyshing, S. 2009. PHP Team Development. Birmingam, United Kingdom: Packt Publishing Ltd. Blanco, G., Borschel, R., Vesterinen, K. & Wage, J. 2010. Doctrine ORM for PHP: Guide to Doctrine 1.2. Version: manual-1.2-1_1-2010-05-05. Sensio Labs. Block, G. 2006. Ten advantages of an ORM (Object Relational Mapper). Luettu 28.3.2016 https://blogs.msdn.microsoft.com/gblock/2006/10/26/ten-advantages-of-an-orm-object-relational-mapper/ Connolly, T & Begg, C. 2005. Database Systems, Fourth Edition. Essex, United King-dom: Pearson Education Limited. Dunglas, K. 2013. Persistence in PHP with Doctrine ORM. Packt Publishing. Doctrine Project Team. 2016. Doctrine 2 ORM documentation. Luettu 28.3.2016 https://media.readthedocs.org/pdf/doctrine-orm/latest/doctrine-orm.pdf Fowler, M. 2003. A short summary of the patterns in Catalog of Patterns of Enterprise Application Architecture. Luettu 17.2.2016. http://martinfowler.com/eaaCatalog/dataMapper.html Fowler, M. 2003. A short summary of the patterns in Catalog of Patterns of Enterprise Application Architecture. Luettu 17.2.2016. http://martinfowler.com/eaaCatalog/unitOfWork.html Freeman, A. 2013, Pro ASP.NET MVC 5. New York, USA: Appress. Koskimies, K. 2000. Oliokirja, 2. muuttumaton painos. Helsinki: Satku – Kauppakaari. Vesterholm, M & Kyppö, J. 2006. Java ohjelmointi, 6. uudistettu painos. Helsinki: Tal-entum Media Oy. Shasankar V, K. 2013. Zend Framework 2.0 by Example Beginner’s Guide. Birming-ham, United Kingdom: Packt Publishing Ltd. Zend Framework 2016. About. Luettu 31.3.2016 http://framework.zend.com/about/