The Yesod Framework

Ein Webrahmenwerk in Haskell

Grundlagen

Philosophie von Yesod

Bei den meisten Websites handelt es sich um solche, die mithilfe von dynamischen Programmiersprachen wie PHP, oder auch Ruby und Python entwickelt wurden, da anhand dieser sehr schnell Resultate erzielt werden können und weil die dynamischen Sprachen sehr weit verbreitet und entsprechend stark unterstützt sind. Diese Sprachen sind jedoch vergleichsweise schwach typisiert, lassen zudem unberücksichtigte Seiteneffekte zu, welche es Entwicklern u. a. schwer machen, Anwendungen in ihrer Vollständigkeit auf Korrektheit zu testen. Das Yesod-Framework, welches von Michael Snoyman entwickelt wurde, verspricht Nutzern die Vermeidung dieser Missstände durch den Einsatz der funktionalen Programmiersprache «Haskell». Gleichermaßen sollen bei einer großen Produktivität Anwendungen entstehen, welche performant ausführbar und aufgrund des nativ implementierten Konzepts der nebenläufigen Programmierung hoch skalierbar sind. Dabei hilft der Webserver Warp, welcher ebenso von Michael Snoyman implementiert wurde und der aktuell schnellste Webserver unter Haskell ist, wie jüngste Benchmark-Ergebnisse zu Tage brachten.[1]

Wie viele andere Webframeworks auch, folgt Yesod dem MVC-Muster. MVC steht dabei für Model-View-Controller und weist damit auf die drei Perspektiven einer Webanwendung hin, welche dieses Paradigma berücksichtigt. Im Zuge der Verbesserung der Übersichtlichkeit und Aufgabentrennung erfolgt eine Differenzierung des Programmcodes gemäß folgender Kategorien.

Model-View-Controller-Perspektiven

Abb. 2.1.: Die Model-View-Controller-Perspektiven[2]

Im Kontext eines Webframeworks spielt für die Perspektive der Datenverwaltung insbesondere die unterstützte Anbindung an Datenbanken zur langfristigen Speicherung von persistenten Daten eine große Rolle. Analog dazu sind bei der Betrachtung der Perspektive «Präsentation» spezielle Template-Engines von Bedeutung, welche eine elegante Trennung von Programmier- und Auszeichnungssprache ermöglichen. Die Perspektive der Business-Logik fügt schließlich alle jeweiligen Programmteile zu einer umfassenden Anwendung zusammen, nimmt Nutzereingaben entgegen, verarbeitet die Anfrage, und gibt die resultierende Ausgabe an den Client zurück (siehe Abb. 2.1.).[3]

Das Yesod-Framework unterstützt Entwickler dabei, Webanwendungen zu produzieren, welche

sind. Mit RESTful ist in diesem Fall die Unterstützung des entsprechenden Softwarearchitekturstils gemeint, welcher die im Kontext des zustandslosen HTTP-Protokolls wohldefinierten Operationen «GET», «POST», «PUT» und «DELETE» berücksichtigt und differenziert.[4] Der grundlegende Ansatz von Yesod ist, die Vorteile des strikten Typsystems von Haskell einzubringen, wo immer dies möglich ist. Dadurch können ganze Klassen von Fehlerfällen ausgeschlossen werden, welche für andere Webframeworks von Relevanz wären. Dem entsprechend fallen auch die dazugehörigen Testfälle weg. Außerdem ermöglicht die hohe Typsicherheit besonderen Schutz gegenüber Angriffen auf die Webanwendung wie beispielsweise SQL-Injections. U. a. mit der Einführung von typsicheren URLs wird an einem Problem angesetzt, welches das World Wide Web von Natur aus mit sich bringt. Das WWW ist nicht typsicher, da es sich bei allen übertragenen Daten um einfache Bytes handelt, die es Anwendungsentwicklern zunächst unmöglich machen, zwischen unterschiedlichen Datentypen zu unterscheiden. Um diesen Fehlerquellen entgegen zu wirken, fordert Yesod sowohl bei der Übertragung von Formular- oder Sitzungsdaten, als auch beim Speichern und Laden von persistenten Informationen die Angabe des entsprechend von der Applikation erwarteten Datentyps.[5] Eine spezielle Rolle bei der Vermeidung von Sicherheitslücken und Fehlern kommt dem Compiler zugute, welcher dafür sorgt, dass nur Programme ausgeführt werden, welche den Vorgaben des Frameworks entsprechen. Dass für die Nutzung von Yesod nicht ein einziges Paket geladen werden muss, welches das komplette Framework enthält, sondern einzelne individuelle Module unabhängig voneinander installiert werden können, um möglichst effizient zu arbeiten, versteht sich für ein Webframework in der heutigen Zeit fast schon von alleine.[6] Beispielsweise sind die Pakete «Persistent» und «Hamlet» auch unabhängig von Yesod nutzbar.

Installation

Die Installation des Yesod-Frameworks ist in wenigen Schritten innerhalb kurzer Zeit durchführbar.[7]

  1. Zunächst ist die Haskell Platform einzurichten.
  2. Direkt im Anschluss muss mit dem Kommandozeilenbefehl cabal update die Liste der inkludierten Pakete aktualisiert werden.
  3. Mit dem Befehl cabal install yesod erfolgt die Installation von Yesod.
  4. Der Befehl yesod init erstellt ein neues Projekt. Ein Assistent führt im Anschluss durch den Einrichtungsprozess für das Grundgerüst des Projekts. Dabei ist der Name des Entwicklers, sowie der Name des anzulegenden Projekts und des Verzeichnisses anzugeben, in welchem die Ordnerstruktur zu generieren ist. Außerdem ist noch die Kennung der Foundation zu definieren, deren Relevanz im nachfolgenden einführenden Beispiel geklärt wird. Nachdem der Entwickler bestimmt hat, ob und über welches Backend die Interaktion mit persistenten Daten erfolgen soll, werden die Dateien entsprechend der Vorgaben in dem eingegebenen Verzeichnis generiert (siehe Abb. 2.2.).
  5. Aus dem Projektverzeichnis heraus können mit dem Befehl cabal install --only-dependencies alle zusätzlichen Support-Bibliotheken installiert werden.
  6. Die Webanwendung ist unter http://localhost:3000 erreichbar, sobald der Befehl yesod devel ausgeführt wurde.
Grundgerüst eines mit Yesod angelegten Projekts

Abb. 2.2.: Das Grundgerüst eines mit Yesod angelegten Projekts

Weitere Informationen bzgl. der Installation sind ebenso auf der offiziellen Website, dem Yesod Web, verfügbar.

Einführendes Beispiel

Das folgende Beispiel soll einen Einstieg in die bei Yesod praktisch angewandten Konzepte ermöglichen. Dabei wird davon ausgegangen, dass keine Verzeichnisstruktur, also kein Grundgerüst des Projekts vorhanden ist. Stattdessen wird zugunsten der Übersicht bei der Erläuterung des Beispiels die gesamte Webanwendung innerhalb einer einzigen Haskell-Datei und ohne externe Quellen definiert. In der Praxis werden Entwickler jedoch den Assistenten zur Generierung eines Projektgrundgerüsts präferieren, um die Webapplikation modular aufzubauen und größer aufzuziehen.

1{-# LANGUAGE QuasiQuotes, TypeFamilies, OverloadedStrings #-}
2{-# LANGUAGE MultiParamTypeClasses, TemplateHaskell #-}
3import Yesod
4
5data Links = Links
6
7mkYesod "Links" [parseRoutes|
8/ HomeR GET
9/page1 Page1R GET
10/page2 Page2R GET
11|]
12
13instance Yesod Links where
14    approot _ = ""
15
16getHomeR  = defaultLayout [hamlet|<a href="@{Page1R}">Go to page 1!|]
17getPage1R = defaultLayout [hamlet|<a href="@{Page2R}">Go to page 2!|]
18getPage2R = defaultLayout [hamlet|<a href="@{HomeR}">Go home!|]
19
20main = warpDebug 3000 Links

In Zeile 5 erfolgt zunächst die Bestimmung der Foundation in Form einer Datentypdefinition. Diese bildet einen Referenzpunkt, um die Zuweisung von verschiedenen Mechanismen zu der Webanwendung zu ermöglichen, und ist essentiell für die Funktionsweise von Yesod. Jede Foundation muss Instanz der Yesod-Typklasse sein. Dies geschieht entsprechend in den Zeilen 13 und 14. Die Zeilen 7 bis 11 definieren den Front Controller der Applikation. Wie bei den meisten modernen Webframeworks laufen alle Anfragen, welche den Server erreichen, an diesem Punkt zusammen. Je nach Art der Anfrage beauftragt dieser Front Controller einen entsprechenden Handler damit, die Anfrage weiter zu verarbeiten. Im Beispiel erfolgt die Definition dreier gültiger Routen. Zum einen wird die Startseite definiert, welche an den Handler HomeR weitergeleitet wird, und zum anderen jeweils eine Route für die Webseiten /page1 bzw. /page2, für die die Handler Page1R bzw. Page2R zugeteilt sind. Über die Angabe der Foundation in Zeile 7 erfolgt die Assoziation des Routingsystems mit der Webanwendung.

In den Zeilen 16 bis 18 wird bestimmt, auf welche Weise die angesprochenen Handler den Inhalt ausgeben. An dieser Stelle kommt das von Yesod standardmäßig genutzte Paket «Hamlet» zum Einsatz, welches dazu verwendet wird, das Templatesystem zu implementieren. Im Beispiel werden für die drei definierten Webseiten unterschiedliche Links generiert, welche jeweils zur nächsten Route verweisen.

Zeile 20 enthält schließlich den Aufruf, welcher den Webserver Warp mit der Applikation startet. Auch an dieser Stelle fällt die Assoziation mit der Foundation auf. Im Beispiel horcht der Server auf dem Port 3000 und gibt für sämtliche eingehenden Anfragen Debug-Informationen zurück. Für den Zweck des Deployments stehen entsprechend eigene Funktionen zur Verfügung.[8]