diff --git a/tex/chapters/2-web-ohjelmointi.tex b/tex/chapters/2-web-ohjelmointi.tex index ff065c2..849869d 100644 --- a/tex/chapters/2-web-ohjelmointi.tex +++ b/tex/chapters/2-web-ohjelmointi.tex @@ -22,5 +22,3 @@ Palvelinpuolella tarkoitetaan ohjelman osaa, johon asiakaspuoli yhdistyy noutaak Palvelinpuoleen viitataan usein myös rajapintana (eng. Application Programming Interface, API), sillä tämänkaltaisia HTTP-protokollalla ohjattavia ohjelmia voi käyttää myös muuallakin kuin asiakaspuolen web-ohjelmissa. Rajapinnat voivat myös yhdistyä toisiinsa internetin välityksellä ja näin jakaa tietoja eri palveluiden välillä. Rajapintojen yleistyessä on kehitetty standardeja, joiden mukaan rajapintoja voi rakentaa. Näin rajapinnoista tulee helpompia käyttää kaikille. Yksi näistä standardeista on Representational state transfer (REST) \cite{wiki:rest}, jota pyrin käyttämään tämän insinöörityön projektia ohjelmoidessa. - -\clearpage diff --git a/tex/chapters/3-kielet.tex b/tex/chapters/3-kielet.tex index 29cff54..747bf4d 100644 --- a/tex/chapters/3-kielet.tex +++ b/tex/chapters/3-kielet.tex @@ -11,8 +11,6 @@ Automaattiselle roskienkeruulle on aikaisemmin ollut vaihtoehtona vain manuaalin Rustin yhtenä pääominaisuutena on mainostettu sen uudenlaista näkökulmaa muistinhallintaan: omistajuutta \cite{rust:ownership}. Siinä jokaisella arvolla on omistaja, ja kun omistaja menee näkyvyysalueen ulkopuolelle, niin menevät myös sen omistamat arvotkin, eli ne vapautetaan muistista. Arvojen omistajuutta voi siirtää joko pysyvästi tai väliaikaisesti lainaamalla. -\clearpage - \begin{code} \inputminted{Rust}{code/ownership.rs} \captionof{listing}{Omistajuus Rustissa} @@ -54,8 +52,6 @@ Niissä tapauksissa, joissa tyypille voi olla useita vaihtoehtoja, tai silloin j Koodiesimerkissä \ref{code:rust:type-notation} valitsin arvolle ''age'' tyypin u8, koska se on pienin kokonaislukutyypeistä ja sen arvo voi olla välillä 0-255. Näin voi potentiaalisesti vähentää ohjelman muistin käyttöä. Lisäksi tyypeillä voi myös karkeasti rajata funktion parametrien arvojen vaihteluväliä. Esimerkiksi jos on kirjoittamassa funktiota, joka ottaa parametrina henkilön iän, u8 on hyvä valinta, koska ihmisen ikä ei voi olla negatiivinen ja yksikään ihminen tuskin elää yli 255 vuotta. -\clearpage - Edellä mainittu tyyppi u8 on niin kutsuttu etumerkitön kokonaisluku (eng. \textbf{u}nsigned integer). Etumerkillisissä kokonaisluvuissa (eng. signed integer) käytetään yksi bitti merkkaamaan sitä, onko luku positiivinen vai negatiivinen. Etumerkittömissä luvuissa tätä ei tehdä, joten luku voi olla hieman isompi kuin etumerkillinen luku, mutta se ei voi olla negatiivinen. \def\2^#1{\hbox to1.6em{$2^{#1}$\hss}} @@ -109,8 +105,6 @@ Toisin kuin C- ja C++ -kielissä, Rustissa on oletuksena etumerkittömien kokona \label{code:rust:integer-overflow} \end{code} -\clearpage - \subsection{Muuttumaton data} Rustissa kaikki arvot ovat oletuksena muuttumattomia (engl.\ immutable). Jos muuttumattoman datan sijasta tarvitsee muuttujia (engl. mutable), voi käyttää avainsanaa ''mut'', esimerkiksi \mintinline{Rust}{let mut name = "Marko"}. Myös lainaukset suoritetaan oletuksena muuttumattomasti ja muutettavan lainauksen voi tehdä samalla avainsanalla, esimerkiksi \mintinline{Rust}{say_hello(&mut name)} @@ -122,8 +116,6 @@ Rustia kehitettäessä on aina ollut tavoitteena luotettavuus. Tämä tarkoittaa Myös Rustin kääntäjään on panostettu paljon, ja virheiden sattuessa se on todella hyvä työkalu ohjelmoijalle. Se alleviivaa ongelmakohdat ja selittää lyhyesti, mistä ongelma johtuu. Jossain tapauksissa kääntäjä jopa antaa pieniä koodin pätkiä, mistä voi olla apua ongelman ratkaisemisessa [koodiesimerkki \ref{code:rust:help}]. -\clearpage - \begin{code} \inputminted[linenos=false]{shell}{code/compiler-help} \captionof{listing}{Rustin kääntäjä auttaa unohtuneen importin lisäämisessä} @@ -156,8 +148,6 @@ Yksi todella mielenkiintoinen ominaisuus Rustissa on makrot. Se on toiminnallisu \label{code:rust:macro} \end{code} -\clearpage - Makron sisällä suluissa olevat lauseet ovat verrattavissa Rustin ''match''-lauseeseen. Kun makron syöte vastaa jotakin näistä lauseista, hakasulkujen sisällä oleva koodi generoidaan. Makrossa käytetty ''println!()'' on myös itsessään makro, joka tulee Rustin ''std'' -kirjaston mukana. \bigskip @@ -179,8 +169,6 @@ Aloitin itsekin opiskelemaan Rustia vain hieman ennen tämän insinöörityön a \label{sect:paketinhallinta} Rustin paketinhallinta on toteutettu Cargo-nimisellä ohjelmalla. Sitä voi käyttää koko ohjelmiston elinkaaren ajan aina projektin luomisesta sen julkaisemiseen. Cargon käsittelemiä paketteja kutsutaan laatikoiksi (eng. crate), jotka julkaistaan crates.io \cite{rust:cratesio} pakettirekisterissä. Laatikot voivat myös olla riippuvaisia toisista laatikoista. Laatikon tiedot ja riippuvuudet määritetään Cargo.toml-tiedostossa [koodiesimerkki \ref{code:rust:cargo-toml}]. -\clearpage - \begin{code} \inputminted{TOML}{code/Cargo.toml} \captionof{listing}{Projektin palvelinpuolen Cargo.toml} @@ -194,8 +182,6 @@ WebAssembly \cite{webassembly:home} on kehitteillä oleva asiakaspuolen ohjelmoi Kehittäjän ei ole tarkoitus kirjoittaa WebAssemblya itse, vaan käyttää työkaluja, joilla olemassa olevia ohjelmointikieliä voi kääntää WebAssemblyksi. Rust on tästä hyvä esimerkki, sillä WebAssembly on yksi sen kääntäjän natiiveista ''targeteista'', samalla tavalla kuin vaikka x86-prosessorit. -\clearpage - WebAssembly on siis ensisijaisesti binääriformaatti, mutta sen voi muuntaa myös tekstiformaatiksi, jonka nimi on WebAssembly text \cite{webassembly:text}. WebAssembly text käyttää syntaksissaan S-lausekkeita \cite{s-expression}. Se on notaatio puurakenteiselle datalle, joka on kehitetty Lisp-ohjelmointikieltä varten, joten WebAssembly text muistuttaa syntaksiltaan hyvin paljon Lispiä. WebAssembly textiä käytetään tilanteissa, joissa ihmisen täytyy ymmärtää, mitä koodissa tapahtuu. Tätä hyödynnetään esimerkiksi WebAssemblyn sisäisessä kehityksessä ja web-ohjelmistojen debuggereissa. \bigskip diff --git a/tex/chapters/4-projekti.tex b/tex/chapters/4-projekti.tex index 0a12d01..8306284 100644 --- a/tex/chapters/4-projekti.tex +++ b/tex/chapters/4-projekti.tex @@ -4,8 +4,6 @@ Tein insinöörityön yhteydessä full-stack projektin, jossa sekä palvelin- et \section{Kehitysympäristön asennus} Rust-projektin aloittamiseksi kehittäjä tarvitsee koneelleen Rustin paketinhallintatyökalun, Cargon (katso luku \ref{sect:paketinhallinta}). Olen itse Linux-käyttäjä, joten sain asennettua Cargon Linux-jakeluni ohjelmavarastosta. Windows-käyttäjille suosittelen käyttämään Rustup-asennusohjelmaa. Lisää tietoa Rustin asentamisesta saa Rustin kotisivuilta \cite{rust:install}. -\clearpage - Projektin saa initialisoitua komennolla \mintinline{shell}{cargo init projektinnimi}. Tämä komento luo hakemiston ''projektinnimi'', minkä sisällä on Cargon konfiguraatiotiedosto Cargo.toml, jossa voi määrittää projektin tiedot ja riippuvuudet. Lähdekoodi sijaitsee hakemistossa ''src''. Cargo kirjoittaa hakemistoon valmiiksi ''main.rs'' -tiedoston, jossa on ''Hello world!'' esimerkkikoodi. ''main.rs'' on aina Rust-ohjelman ensimmäiseksi suoritettava tiedosto, eli niin kutsuttu entrypoint. ''main.rs''-tiedoston sisällä pitää olla ''main()''-funktio, josta ohjelman suoritus alkaa. Projektin voi suorittaa komennolla \mintinline{shell}{cargo run}. @@ -20,8 +18,6 @@ Palvelinpuolen kehykseksi valikoitui Actix web. Se on käytännössä vastine Ja Actix web on puolestaan rakennettu hyödyntämällä Actix-sovelluskehystä, joka 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. -\clearpage - 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 (eng. structure) [koodiesimerkki \ref{code:rust:registeruser}]. \bigskip @@ -44,8 +40,6 @@ Kun koodiesimerkin \ref{code:rust:registeruser} funktioon ''register'' saapuu ko Palvelinpuolen initialisointi ja käynnistäminen löytyvät liitteestä \ref{appx:actix}. -\clearpage - \subsection{Todentaminen} Actix webin modulaarisuus mahdollisti myös helposti tarvittavien väliohjelmistojen sisällyttämisen ohjelman toimintaan. Actix identity -paketista löytyi tarvittavat palikat, joilla sain lisättyä itse kirjoittamani käyttäjän todentamistoiminnallisuuden suojaamaan haluttuja reittejä. @@ -96,8 +90,6 @@ Projektin asiakaspuolen aloittaminen vaati aika paljon tutkimustyötä. Rust-koo Valitsemani sovelluskehys tukee molempia kirjastoja, mutta päädyin kuitenkin valitsemaan stdweb:n. Suurimpana syynä oli projektin aloittamisen helppous, joka tehdään Cargon liitännäisellä cargo-web. Toisena syynä oli, että WebAssembly-ohjelman paketointi web\char`_sys:n kanssa on tätä kirjoittaessani riippuvainen NodeJS:stä, kun taas stdweb ei vaadi NodeJS:n asennusta kehittäjän koneelle ollenkaan. -\clearpage - WebAssembly-koodin suorittamiseksi selain tarvitsee pienen pätkän JavaScriptiä, joka tekee tarvittavat toimet WebAssembly-ohjelman käynnistämiseksi. Tämän koodin generoi puolestani cargo-web. Lisäksi JavaScriptin suorittamiseen tarvitaan yksi HTML-tiedosto. Tähän tiedostoon voi myös sisällyttää metadataa, kuten esimerkiksi sivuston otsikon, joka näkyy selaimen välilehdessä. Tähän tiedostoon linkitetään myös kaikki muu staattinen data, kuten tyylimääritykset. Nämä tiedostot laitoin käytännön mukaisesti static-nimiseen hakemistoon asiakaspuolen projektin juureen. Tämän hakemiston linkitin symbolisella linkillä palvelinpuolen projektiin, jonka HTTP-serveri voi sitten lähettää HTML-dokumentin, JavaScript-tiedoston ja WebAssembly-binäärin käyttäjän selaimelle. \subsection{Kehys} @@ -108,8 +100,6 @@ Asiakaspuolen sovelluskehykseksi valitsin Yew:n\cite{yew:home}. Yew muistuttaa h \label{sect:ulkonäkö} Olen JavaScript-maailmassa tottunut siihen, että käyttöliittymäkehyksiin löytyy usein kirjasto, joka tarjoaa valmiit tyylimääritykset, mutta en löytänyt vastaavaista kirjastoa, joka toimisi Yew:n kanssa. Kaikki käyttöliittymän elementit olivat siis selaimen oletustyylisiä. En halunnut ryhtyä tässä projektissa kirjoittamaan CSS-määrityksiä alusta alkaen, joten päädyin käyttämään UIkittiä\cite{uikit}. UIkit on CSS-kirjasto, missä on paljon valmiita ja hyvännäköisiä tyylimäärityksiä. UIkitin dokumentaatio on laaja ja siellä on paljon esimerkkejä, joten alkuun pääsi todella nopeasti [kuva \ref{fig:login}]. -\clearpage - \begin{figure}[h] \centering \includegraphics[width=\linewidth]{illustration/login.png} @@ -156,8 +146,6 @@ Tuloksena syntyi yksinkertainen web-ohjelma, jossa on toimiva sisäänkirjautumi \end{figure} -\clearpage - Ohjelman juuressa renderöidään komponentti ''ProtectedComponent'', missä on yksi nappi, jolla voidaan noutaa dataa palvelimelta. Tämä data on suojattu niin, että pyynnön mukana pitää olla eväste, jonka sisällä on JWT, joka sitten validoidaan palvelinpuolella. Jos validointi onnistuu, suojattu data lähetetään asiakkaalle. Asiakaspäässä HTTP-statuskoodin perusteella näytetään joko noudettu data, tai "403 Unauthorized". Reitissä ''/login'' renderöidään ''LoginComponent'', joka koostuu kahdesta tekstikentästä, käyttäjänimi ja salasana, sekä napista, jolla kirjautumistiedot voi lähettää palvelimelle. Onnistumisen kirjautumisen jälkeen palvelimelta lähetetty eväste tallennetaan selaimen muistiin.