\chapter{Projekti} Tein opinnäytetyön yhteydessä fullstack-projektin, missä sekä palvelin- että asiakaspuolen ohjelmointi tehtiin Rustilla. Tarkoituksena ei ollut saada aikaiseksi mitään todella monimutkaista ohjelmaa, vaan puhtaasti arvioida Rustin soveltuvuutta web-ohjelmointiin. \section{Palvelinpuoli} Palvelinpuolen rungoksi valikoitui Actix web. Se on käytännössä vastine JavaScript-maailman Express.js:lle, eli se hoitaa HTTP-palvelimen työtä ja reitittää GET ja POST pyynnöt ohjelman oikeille funktioille. Actix web on puolestaan rakennettu hyödyntämällä Actix frameworkiä, mikä on rakennettu löyhästi actor-mallin pohjalta. Actor-malli\cite{wiki:actor} on Carl Hewittin vuonna 1973 luoma matemaattinen ja tietotekninen malli rinnakkaisajosta. Tämän ansiosta Actix web on hyvin suorituskykyinen ja helposti skaalautuva ratkaisu rajapintoja rakennettaessa. Actix web on myös hyvin integroitu Rustin vahvaan tyypitykseen. Erityisen vaikuttavaa oli se, että esimerkiksi tietyn rajapinnan päätepisteen POST-pyyntöön pystyy määrittämään parametriksi tietyn rakenteen (struct). Esimerkiksi näin: \begin{minted}{rust} struct RegisterUser { username: String, password: String, admin: bool, password_confirmation: String, } #[post("/auth/register")] fn register( new_user: actix_web::web::Json, ) -> Result { register(new_user); } \end{minted} Tällöin varmistutaan automaattisesti siitä, että kun asiakkaan POST-pyyntö saapuu tähän funktioon, kaikki data on oikeanlaista tyyppiä ja kaikki tarvittava data on pyynnössä mukana. Verrattuna JavaScriptiin, jossa ei ole tyyppejä, kaikki vastaanotettava data pitäisi tarkastaa käsin. Jatkaakseni edellistä esimerkkiä, otetaan seuraava JSON-merkkijono: \begin{minted}{JSON} { "username": "TestUser", "password": "verysecurepassword", "admin": 3, } \end{minted} Koska tässä JSON-objektissa ''admin'' ei ole tyyppiä boolean, Actix vastaa ''400 Bad Request''. Actix webin modulaarisuus mahdollisti myös helposti tarvittavien väliohjelmistojen sisällyttämisen ohjelman toimintaan. Actix identity -paketista löytyi tarvittavat palikat itse kirjoittamani sisäänkirjautumistoiminnallisuuden lisäämisen suojattuihin reitteihin. Siinä käytin JSON Web Tokeneita, jotka lähetettiin onnistumisen kirjautumisen jälkeen asiakkaalle, ja jotka asiakas sitten lähettää serverille suojattuja reittejä käytettäessä. Tietokannaksi valikoitui itselleni tuttu MySQL. Relaatiotietokannan sai helposti yhdistettyä Rust-koodiini Diesel ORM:llä. Diesel on tähän mennessä käyttämistäni ORM-kirjastoista selkeästi mukavin käyttää. Käytännöllisimmät ominaisuudet kehittäjän näkökulmasta olivat Dieselin mukana tuleva komentorivikäyttöliittymä ja migraatiot. Jokaiselle taululle luodaan uusi migraatio, esimerkiksi \code{diesel migration generate users}, jonka jälkeen dieselin luomaan hakemistoon kirjoitetaan up.sql ja down.sql tiedostot, eli ohjeet siitä, miten tämä taulu luodaan ja poistetaan. Taulu viedään tietokantaan komennolla \code{diesel migration run} ja taulun voi poistaa ja luoda uudelleen komennolla \code{diesel migration redo}. Tämä mahdollistaa myös samalla sen, että versiohallintaan voi tallentaa useita versioita samasta taulusta ja palata helposti takaisin vanhempaan versioon jos uudemman kanssa ilmenee ongelmia. Edellä mainitut työkalut helpottivat tietokannan kehitystä huomattavasti. Usein varsinkin projektin alkuvaiheilla tietokanta muuttuu jatkuvasti ja usein tulee tarve poistaa ja luoda tietokanta uudelleen. Monet pitävät kehittäjät juurikin tällaista Dieselin up.sql kaltaista tiedostoa versiohallinnassa ja tarpeen mukaan poistavat tietokannan käsin ja liittävät komennon tiedostosta tietokannan komentorivikäyttöliittymään. \section{Asiakaspuoli} \clearpage