Ohjelmistokehityksessä törmää yllättävän usein projekteihin, joissa tietokantamalleja (Entity) käytetään sellaisenaan käyttöliittymän tietomallina. Moni perustelee ratkaisua sillä, että se on suoraviivainen ja nopea tapa siirtää dataa paikasta toiseen. Lyhyellä aikavälillä se voikin tuntua tehokkaalta, mutta pidemmällä aikavälillä tämä lähestymistapa voi aiheuttaa enemmän ongelmia kuin ratkaisee.
Tietokantamallien ensisijainen tehtävä on kuvata tietokannan rakennetta. Mallit sisältävät teknisiä yksityiskohtia kuten JPA-annotaatioita, relaatioita muihin tauluihin ja tietokantakohtaisia rajoitteita. Käyttöliittymä taas tarvitsee tietoa eri muodossa - yksinkertaistettuna, käyttäjäystävällisenä ja usein useista eri lähteistä koostuvana.
Kun tietokantamalleja käytetään suoraan käyttöliittymässä, muodostuu näiden kahden kerroksen välille riippuvuus. Jokainen muutos tietokantarakenteessa heijastuu välittömästi käyttöliittymään ja päinvastoin. Tämä tekee järjestelmästä hauraan ja vaikeasti ylläpidettävän. Yksinkertainen sarakkeen nimen muutos voi vaatia muutoksia läpi koko sovelluksen.
Rajojen rikkominen näkyy turvallisuudessa
Tietokantamallit eivät sisällä ainoastaan rakennetta, vaan myös tietoa, jota ei välttämättä haluta paljastaa ulospäin. Kun nämä mallit tuodaan sellaisenaan käyttöliittymään, avataan vahingossa pääsy tietoihin, joiden ei olisi pitäisi koskaan poistua palvelimelta.
Käyttöliittymän tehtävä ei ole esittää kaikkea, mitä tietokanta tietää. Tietokannan lukeminen sellaisenaan ei merkittävästi eroa Excelin lukemisesta ilman kuvia. Käyttöliittymän tehtävä on näyttää käyttäjälle relevanttia, ymmärrettävää ja kontekstisidonnaista tietoa. Kun tietokantamalli ja käyttöliittymä on erotettu toisistaan, voidaan määrittää tarkasti, mitä tietoa liikkuu ja missä muodossa. Tämä on sekä tietoturvan että ylläpidettävyyden kannalta kriittistä.
DTO-mallit eriyttävät vastuut
Ratkaisuksi on ajatus erillisestä siirtokerroksesta, joka toimii välikätenä tietokannan ja käyttöliittymän välillä. Tätä varten luodaan niin sanottuja DTO-malleja (Data Transfer Object), jotka muotoilevat datan juuri siihen muotoon, jota käyttöliittymä tarvitsee. Jos käyttöliittymiä on useampia jokaisella voi olla omat DTO-mallit.
DTO ei välitä siitä, miten tieto on tallennettu tietokantaan, vaan se keskittyy siihen, millaisessa muodossa tieto välitetään käyttöliittymälle. Tämä mahdollistaa sen, että taustalla olevaa tietorakennetta voidaan muuttaa ilman, että käyttöliittymä menee rikki. Samalla voidaan säilyttää sovelluksen eheys ja estää tietovuodot.
Erot tietomalleissa tuovat selkeyttä kehittäjien työhön. Jokaisella sovelluksen kerroksella on oma roolinsa: tietokantakerros huolehtii tallennuksesta, palvelukerros liiketoimintalogiikasta ja käyttöliittymä datan esittämisestä. Kun nämä pidetään erillään, sovelluksen rakenne pysyy ymmärrettävänä ja hallittavana myös vuosien päästä.
Pitkän aikavälin hyödyt
Lyhyellä tähtäimellä suora yhteys tietokannan ja käyttöliittymän välillä saattaa tuntua järkevältä. Se poistaa välikerroksen ja vähentää kirjoitettavaa koodia. Todellisuudessa kuitenkin jokainen väliin jätetty kerros on nostettua teknisen velan lainaa. DRY ja KISS fanit tulevat kiukuttelemaan abstraktiotason tarpeellisuudesta hamaan loppuun asti, mutta en henkilökohtaisesti halua ikinä joutua muuttamaan käyttöliittymän koodia sen takia, että siirsin tietokannan aikaisemman booleanina tallennetun kentän dynaamisesti laskettavaksi arvoksi palvelimella.
Teksti on kirjoitettu JPA-silmälasien lävitse, mutta väitän ratkaisun tarpeen pätevän myös tilanteisiin missä kyselyt kirjoitetaan SQL:llä ja palautetaan jäsä-palvelimelta jäsä-käyttöliittymään.