im studiengang medieninformatik - htw dresdenfritzsch/sf/diplomarbeit_helga... · 3.3.1...
TRANSCRIPT
Hochschule für Technik und Wirtschaft Dresden (FH)Fachbereich Informatik/Mathematik
Diplomarbeit
im Studiengang Medieninformatik
Thema: Analyse und Vergleich von WebFrameworks im Bereich der agilen Webentwicklung anhand einer Beispielanwendung
Eingereicht von: Helga Nickel
Eingereicht am: 08.03.2010
Betreuer: Prof. Dr.Ing. Thomas Wiedemann, HTW Dresden
Inhaltsverzeichnis
Abbildungsverzeichnis.............................................................................................................IVTabellenverzeichnis...................................................................................................................VQuellcode.................................................................................................................................VIAbkürzungsverzeichnis.........................................................................................................VIII
1 Einleitung................................................................................................................................11.1 Motivation........................................................................................................................11.2 Aufgabenstellung.............................................................................................................11.3 Aufbau der Arbeit............................................................................................................2
2 Klassische und agile Methoden der Softwareentwicklung......................................................32.1 Aktueller Stand der Softwareentwicklung.......................................................................32.2 Klassische Methoden der Softwareentwicklung..............................................................42.3 Agile Methoden der Softwareentwicklung......................................................................6
2.3.1 Das agile Manifest....................................................................................................62.3.2 Prinzipien.................................................................................................................72.3.3 Methoden und Prozesse...........................................................................................8
2.4 Klassische versus agile Methoden.................................................................................103 Agile Webentwicklung..........................................................................................................12
3.1 Grundlagen der Webentwicklung..................................................................................123.2 Agile Web Applikation Frameworks.............................................................................133.3 Prinzipien agiler Webentwicklung.................................................................................14
3.3.1 MVCArchitektur...................................................................................................143.3.2 Konvention über Konfiguration.............................................................................153.3.3 DRYPrinzip..........................................................................................................163.3.4 Objektrelationales und URLMapping...................................................................173.3.5 CreateReadUpdateDeletePrinzip......................................................................173.3.6 KISSPrinzip..........................................................................................................183.3.7 AjaxUnterstützung................................................................................................183.3.8 Testgetriebene Entwicklung...................................................................................18
3.4 Auswahl der WebFrameworks......................................................................................194 Eingesetzte Technologien......................................................................................................22
4.1 Ruby on Rails.................................................................................................................224.1.1 Einführung in Ruby on Rails..................................................................................224.1.2 MVCArchitektur mit Rails....................................................................................234.1.3 ActiveRecord..........................................................................................................244.1.4 ActionController.....................................................................................................254.1.5 URLKonfiguration................................................................................................284.1.6 ActionView.............................................................................................................28
I
4.2 Django............................................................................................................................314.2.1 Einführung in Django.............................................................................................314.2.2 MTVArchitektur mit Django................................................................................324.2.3 Modell....................................................................................................................334.2.4 Die URLKonfiguration.........................................................................................344.2.5 Automatische Administrationsoberfläche..............................................................344.2.6 View.......................................................................................................................354.2.7 Template.................................................................................................................36
4.3 Grails.............................................................................................................................384.3.1 Einführung in Grails..............................................................................................384.3.2 MVCArchitektur mit Grails..................................................................................394.3.3 Modell....................................................................................................................404.3.4 Controller...............................................................................................................424.3.5 View.......................................................................................................................434.3.6 Die URLKonfiguration.........................................................................................44
5 Definition der Evaluierungskriterien....................................................................................456 Entwurf und Implementierung..............................................................................................48
6.1 Anforderungen an die Beispielanwendung....................................................................486.2 Implementierung mit Ruby on Rails.............................................................................52
6.2.1 Anwendungsrahmen und Verzeichnisstruktur........................................................526.2.2 Modelle anlegen.....................................................................................................536.2.3 Implementierung des User Interfaces....................................................................546.2.4 Suchfunktion mit Ajax...........................................................................................576.2.5 RailsAuthentifizierung.........................................................................................59
6.3 Realisierung mit Django................................................................................................606.3.1 Anwendungsrahmen und Verzeichnisstruktur........................................................606.3.2 Modelle anlegen.....................................................................................................616.3.3 Anwendung der Administrationsoberfläche..........................................................626.3.4 Implementierung des User Interfaces....................................................................636.3.5 Suchfunktion mit Ajax...........................................................................................65
6.4 Realisierung mit Grails..................................................................................................676.4.1 Anwendungsrahmen und Verzeichnisstruktur........................................................676.4.2 DomainModelle....................................................................................................696.4.3 Implementierung des User Interfaces....................................................................706.4.4 Suchfunktion mit Ajax...........................................................................................726.4.5 Grails Authentifizierung........................................................................................74
7 Evaluierung...........................................................................................................................767.1 Funktionale Kriterien.....................................................................................................76
7.1.1 Datenbank und Modelle..........................................................................................767.1.2 Controller................................................................................................................787.1.3 URLRouting..........................................................................................................797.1.4 Templates................................................................................................................80
II
7.1.5 Daten und Benutzer Verwaltung..........................................................................817.2 Dokumentation und ProjektCommunity......................................................................837.3 Support...........................................................................................................................86
7.3.1 Installation..............................................................................................................867.3.2 Entwicklungsprozess..............................................................................................877.3.3 Ajax und PluginSupport......................................................................................897.3.4 DeploymentSupport und Webhosting...................................................................90
7.4 Entwicklungseffizienz...................................................................................................927.5 Sonstige Kriterien..........................................................................................................95
7.5.1 Programmiersprache...............................................................................................957.5.2 Security..................................................................................................................967.5.3 JobPerspektiven....................................................................................................98
7.6 Ergebnisse der Evaluierung..........................................................................................1008 Zusammenfassung...............................................................................................................104Literaturverzeichnis................................................................................................................105Anhang A Screenshots............................................................................................................111Anhang B Installation.............................................................................................................118
B.1 Die Ruby on RailsInstallation....................................................................................118B.2 Die DjangoInstallation...............................................................................................119B.3 Die GrailsInstallation.................................................................................................122
Anhang C Einstellungen des Projektes...................................................................................123C.1.1 Einstellungen des DjangoProjektes.........................................................................123C.1.2 URLKonfiguration des DjangoProjektes...............................................................124C.2 Einstellungen des GrailsProjektes.............................................................................125
Anhang D DeploymentSupport und Webhosting..................................................................127D.1 Ruby on Rails Webhosting..........................................................................................127D.2 Django Webhosting.....................................................................................................128D.3 Das Deployment einer GrailsWebanwendung...........................................................128
Anhang E Security.................................................................................................................129E.1 SQLInjection..............................................................................................................129E.2 CrossSiteScriptingInjection.....................................................................................131E.3 CrossSiteRequestForgery........................................................................................133E.4 SessionAngriffe.........................................................................................................134
Anhang G CD.........................................................................................................................135
III
Abbildungsverzeichnis
Abbildung 2.1: Vorgehensmodelle.............................................................................................4Abbildung 2.2: Ablauf einer iterativen Entwicklung (Quelle: [MunzSoergel07]).....................5Abbildung 2.3: Agile Begriffe...................................................................................................6Abbildung 2.4: Das agile Manifest (Quelle: [AgileManifesto]).................................................6Abbildung 2.5: XP Komponenten..............................................................................................9Abbildung 2.6: Der Scrum – Prozess (Quelle: [ScrumMaster])..............................................10Abbildung 3.1: Datenfluss bei einer Webanwendung..............................................................12Abbildung 3.2: MVCArchitektur............................................................................................15Abbildung 4.1: Bestandteile von Rails (Quelle:[RabWeb]).....................................................23Abbildung 4.2: Datenaustausch vom Controller zum View.....................................................27Abbildung 4.3: RailsRouting..................................................................................................28Abbildung 4.4: Verwendung von Partials................................................................................30Abbildung 4.5: Bestandteile von Django.................................................................................32Abbildung 4.6: Ablauf von Django Request und Response (Quelle: [DjB])...........................33Abbildung 4.7: GrailsKomponenten (Quelle: [JavaMag09])..................................................39Abbildung 4.8: Bearbeitung einer Anfrage in Grails...............................................................40Abbildung 4.9: Syntax des dynamischen Finders....................................................................41Abbildung 6.1: Klassenmodell der Beispielanwendung...........................................................48Abbildung 6.2: Skizze der Seitennavigation............................................................................49Abbildung 6.3: Filter................................................................................................................50Abbildung 6.4: AjaxSuchfunktion..........................................................................................51Abbildung 6.5: config/database.yml........................................................................................53Abbildung 6.6: Suchmöglichkeiten..........................................................................................74Abbildung 6.7: RequestmapURL des adminBenutzer...........................................................75Abbildung 7.1: GoogleInsightsSearchFunktion....................................................................84Abbildung 7.2: Die regionale Verteilung der Suchanfragen....................................................85Abbildung 7.3: Implementierungszeit......................................................................................94Abbildung 7.4: Codeeffizienz..................................................................................................95Abbildung 7.5: Die Verbreitung von Programmiersprachen....................................................97Abbildung 7.6: JobAngebote in Deutschland [Stand: Jan.2010]...........................................100Abbildung 7.7: Job Trends für Rails, Django, Grails in den USA..........................................100
IV
Tabellenverzeichnis
Tabelle 1: Klassische versus agile Methoden...........................................................................11Tabelle 2: Übersicht von WebFrameworks.............................................................................20Tabelle 3: Evaluierungskriterien..............................................................................................46Tabelle 4: Bewertung der Evaluierengskriterien......................................................................47Tabelle 5: Zugriffsrechte jeder Benutzerrolle...........................................................................51Tabelle 6: Datenbank und Modelle..........................................................................................78Tabelle 7: URLRouting...........................................................................................................79Tabelle 8: Templates.................................................................................................................81Tabelle 9: Daten und BenutzerVerwaltung............................................................................83Tabelle 10: Dokumentation und ProjektCommunity..............................................................85Tabelle 11: Installation der WebFrameworks..........................................................................86Tabelle 12: Entwicklungsprozess.............................................................................................88Tabelle 13: AjaxUnterstützung und PluginSupport...............................................................90Tabelle 14: DeploymentSupport und Webhosting...................................................................91Tabelle 15: Implementierungszeit............................................................................................93Tabelle 16: Codeeffizienz.........................................................................................................94Tabelle 17: Programmiersprachen............................................................................................95Tabelle 18: Security..................................................................................................................98Tabelle 19: JobAngebote in Deutschland und in den USA.....................................................98Tabelle 20: Übersichtstabelle..................................................................................................101
V
Quellcode
Quellcode 1: Migrationsdatei...................................................................................................24Quellcode 2: Definition einer Modellklasse............................................................................25Quellcode 3: renderMethode..................................................................................................26Quellcode 4: redirect_toBefehl...............................................................................................27Quellcode 5: LayoutDatei.......................................................................................................30Quellcode 6: URLKonfiguration............................................................................................34Quellcode 7: AdminInterfaceKonfiguration in der urls.pyDatei..........................................35Quellcode 8: render_to_responseFunktion.............................................................................36Quellcode 9: Die Verbindung eines Templates........................................................................37Quellcode 10: LayoutDatei.....................................................................................................44Quellcode 11: UrlMappings.groovyDatei...............................................................................44Quellcode 12: Erstellung des StworkDomainModells...........................................................53Quellcode 13: 1:nBeziehung zwischen den Modellen Students und Stworks........................54Quellcode 14: Validierung durch Klassenmethoden................................................................54Quellcode 15: validateMethode der Klasse Student...............................................................54Quellcode 16: mainlayout.rhtmlDatei....................................................................................55Quellcode 17: Navigation der Beispielanwendung...................................................................55Quellcode 18: Paginate Plugin.................................................................................................56Quellcode 19: Definition der Filter in einem index.htmlView...............................................56Quellcode 20: Definition der Filter in einem stworks_controller.rb........................................57Quellcode 21: Ajaxbasiertes Formular in der Datei app/views/stworks/index.rhtml..............58Quellcode 22: searchMethode.................................................................................................58Quellcode 23: config/routes.rb.................................................................................................59Quellcode 24: Modellklasse Student........................................................................................61Quellcode 25: Modellklasse Studentwork................................................................................61Quellcode 26: admin.pyDatei der studentsApplikation.........................................................62Quellcode 27: Optionen des AdminInterfaces........................................................................62Quellcode 28: indexView........................................................................................................63Quellcode 29: readStudentFunktionen....................................................................................64Quellcode 30: readStudent.htmlTemplate...............................................................................64Quellcode 31: URL Definition.................................................................................................64Quellcode 32: Zugriffsbeschränkung.......................................................................................65Quellcode 33: Suchformular in der students/templates/index.htmlDatei...............................66Quellcode 34: JavaScriptFunktion mit jQuery.......................................................................66Quellcode 35: searchFunktion................................................................................................67Quellcode 36: DomainKlasse Student....................................................................................69Quellcode 37: constraintsBlock des StudentDomainModells..............................................69Quellcode 38: toStringMethode..............................................................................................70Quellcode 39: LayoutDatei.....................................................................................................71
VI
Quellcode 40: Die Definition einer paginateMethode............................................................71Quellcode 41: Definition des Filters im Controller..................................................................72Quellcode 42: Rendern der Templates.....................................................................................72Quellcode 43: Suchfeld in der listDatei..................................................................................73Quellcode 44: DomainKlassen in den Suchbereich einbinden...............................................73Quellcode 45: Implementierung einer searchMethode...........................................................74Quellcode 46: Die Zugriffsbeschränkung für die User und GastBenutzerrolle....................75
VII
Abkürzungsverzeichnis
AJAX Asynchronous JavaScript and XML
CRUD Create, Read, Update and Delete
CSS Cascading Style Sheets
DRY Don’t Repeat Yourself
FDD Feature Driven Development
ERB Embedded Ruby
GORM Groovy Object Relational Mapper
GSP Groovy Server Page
HSQL HypersonicSQL
HTML Hypertext Markup Language
HTTP Hypertext Transfer Protocol
IDE Integrated Development Environment
JSP Java Server Page
KISS Keep It Simple and Stupid
MVC ModelViewController
MVT ModelTemplateView
PHP Personal Home Page
SQL Structured Query Language
UI User Interface
URL Uniform Resource Locator
XML Extensible Markup Language
XP eXtreme Programming
VIII
1 Einleitung
1 Einleitung
1.1 Motivation
Die Anforderungen an die Entwicklung von Software haben sich wesentlich geändert. Software muss nicht nur möglichst zeitnah auf den Markt gebracht werden, sondern auch hohen Qualitätsanforderungen des Marktes und der Kundenwünsche gerecht werden. Um den ständig steigenden Anforderungen zu entsprechen, wurden neue Werkzeuge und Methoden für die SoftwareErstellung entworfen, die auf der agilen Softwareentwicklung basieren. Die agile Softwareentwicklung versucht mit geringem Aufwand und wenigen Vorschriften auszukommen.
Heutzutage wird daher im Bereich der agilen Webentwicklung auf so genannte WebFrameworks zurückgegriffen. Die wesentlichen Vorteile der agilen Webentwicklung sind einfache Benutzung und schnelle Erlernbarkeit. Sie liefern sofortige und stabile Entwicklungsergebnisse. Weiterhin können während der Entwicklung Änderungen vom Markt und den Kunden schneller in die Realisierung einfließen. Die Produktivität kann somit wesentlich gesteigert werden.
In den letzten Jahren ist eine Vielzahl von Frameworks zur Erstellung von WebAnwendungen entstanden. Aufgrund der steigenden Anzahl wird es zunehmend schwieriger den Überblick zu bewahren, um für konkrete Aufgaben ein geeignetes WebFramework auswählen zu können. Zu dem gewählten Thema liegen derzeit noch wenige Studien vor. Es besteht aber eine sehr große Nachfrage im Bereich der agilen Webentwicklung.
1.2 Aufgabenstellung
Ziel dieser Diplomarbeit ist die Analyse von bedeutenden WebFrameworks im Bereich der agilen Webentwicklung und ein Vergleich dieser anhand einer Beispielanwendung. Aus Gründen des Umfangs beschränkt sich diese Arbeit auf die wichtigsten WebFrameworks aus dem OpenSourceBereich. Für die Realisierung der Aufgabenstellung sind die klassischen und die agilen Methoden der Softwareentwicklung und die dahinter stehende Philosophie zu untersuchen. Ein weiterer Schwerpunkt liegt dabei auf der Konzeption und der Umsetzung der Beispielanwendung in den drei ausgewählten WebFrameworks. Um den Vergleich durchführen zu können, werden bestimmte Kriterien definiert.
1
1 Einleitung
Anschließend werden die ausgesuchten WebFrameworks anhand der definierten Kriterien eingeordnet, bewertet und diskutiert. Die Funktionsweisen sowie Stärken und Schwächen sind Gegenstand des Vergleichs. Als Ergebnis wird heraus gearbeitet, welches WebFramework derzeit am besten als Entwicklungsbasis für die agile Webentwicklung geeignet ist.
1.3 Aufbau der Arbeit
Eine Untergliederung der Arbeit erfolgt in acht Kapitel. Die grundlegenden Methoden der Softwareentwicklung sind in Kapitel 2 vorgestellt. Im wesentlichen werden die Gründe für den Übergang zur agilen Softwareentwicklung erörtert. Kapitel 3 beschäftigt sich mit dem Thema agile Webentwicklung. Es werden die Werkzeuge für die agile Webentwicklung vorgestellt. Auch sind die wichtigsten Grundprinzipien der agilen Webentwicklung Gegenstand dieses Kapitels. Das Kapitel 4 stellt die wichtigsten technologischen Grundlagen und funktionalen Besonderheiten der ausgewählten WebFrameworks kurz vor. In Kapitel 5 werden die Evaluierungskriterien für den am Ende folgenden Vergleich von ausgewählten WebFrameworks definiert und beschrieben. Die Anforderungen an die Beispielanwendung sind in Kapitel 6 formuliert. Die Realisierung der Beispielanwendung ist ebenfalls der Gegenstand des Kapitels. In Kapitel 7 wird die Evaluierung der drei ausgewählten WebFrameworks durchgeführt. Abschließend sind die Ergebnisse der Arbeit in Kapitel 8 zusammengefasst.
2
2 Klassische und agile Methoden der Softwareentwicklung
2 Klassische und agile Methoden der Softwareentwicklung
In diesem Kapitel werden die wichtigsten Vorgehensweisen der klassischen und agilen Softwareentwicklung erläutert, was sich hinter dem Begriff „Agilität” verbirgt und wie sich dieser von der klassischen Softwareentwicklung abgrenzt. Diese Grundlagen sind für das Verständnis der Diplomarbeit von Bedeutung.
2.1 Aktueller Stand der Softwareentwicklung
Kaum eine Branche ist dynamischer als die ITBranche. Kurze Releasezyklen und häufige Technologiewechsel sind kennzeichnend für die hohe Dynamik dieser Branche. Die Projekte zur Entwicklung von Software waren vor Jahren noch relativ klein und übersichtlich. Im Laufe der Zeit wurden die Projekte jedoch immer umfangreicher und komplizierter. Die traditionelle Vorgehensweise versucht durch eine möglichst genaue Planung, alle im Laufe des Projekts kommenden Probleme auszuschließen. Der Kunde muss seine Anforderungen an die neue Software schon vor Projektbeginn bestimmen. Aber in den meisten Fällen stellt sich erst im Laufe des Entwicklungsprozesses heraus, welche Funktionen im Einzelnen überhaupt benötigt werden. Die Integration von neuen Anforderungen an das System ist meist mit weiteren Kosten und Zeitverzögerungen verbunden.
Auf Grund eines sich ständig und rapide verändernden Marktes, fällt es bei der traditionellen Projektplanung zunehmend schwer, alle Anforderungen im voraus zu bestimmen und in den Plan aufzunehmen. Um dem Markt gerecht zu werden, muss man den Kunden die Möglichkeit bieten auch während der Projektlaufzeit Veränderungen am Plan vornehmen zu können und auf unvermeidbare Änderungen schnell und effektiv zu reagieren. Aus wirtschaftlicher Sicht ist es auch sehr bedeutsam die Zykluszeit vom Projektbeginn, wo eine neue Anforderung geplant ist, bis zum Projektende, wo das neue Projekt in Produktion gehen kann, zu minimieren.
Projekte mit sich ändernden Anforderungen benötigen andere Entwicklungsmethoden, die schneller und flexibler auf diese Änderungen reagieren. Deshalb zeigte der Trend in der Softwareentwicklung in der letzten Jahren immer mehr in die Richtung agiler Entwicklungsmethoden zu gehen. Der agile Ansatz ist ein Versuch, die Probleme der klassischen Softwareentwicklung in den Griff zu bekommen. Die Strukturierung und Steuerung der Prozesse in der Softwareentwicklung wird durch die Vorgehensmodelle beschrieben. Ein Vorgehensmodell hilft einen Prozess der Softwareentwicklung in strukturierten Phasen zu organisieren.
3
2 Klassische und agile Methoden der Softwareentwicklung
Jeder Phase sind entsprechende Methoden und Techniken der Organisation zugeordnet. In der klassischen oder traditionellen Softwareentwicklung sind eine Reihe von Vorgehensmodellen zur Anwendung gekommen. Es gibt auch zahlreiche agile Vorgehensmodelle. Abbildung 2.1 zeigt auszugsweise klassische und agile Vorgehensmodelle.
2.2 Klassische Methoden der Softwareentwicklung
Klassische Vorgehensmodelle kann man in zwei Klassen teilen, sequentielle und iterativeinkrementelle Vorgehensmodelle. Das sequentielle Paradigma bezeichnet ein Vorgehen mit klar definierten Phasen und Ergebnissen. Die Entwicklungsphasen werden nacheinander durchlaufen. Wenn eine Phase beginnt, wird die vorangegangene Phase nicht mehr wiederholt. Das bekannteste Vorgehensmodell für sequenzielle Softwareentwicklung ist das Wasserfallmodell. Beim Wasserfallmodell wird der Entwicklungsprozess in einzelne Phasen organisiert. Die Phasen werden nacheinander ausgeführt. Jede Phase muss vollständig abgeschlossen werden bevor die nächste Phase beginnt.1 Die sequentielle Vorgehensweise bietet viele Vorteile:
• Phasen sind klar abgegrenzt• Einfache Planung und Kontrolle des Prozesses• Das Modell hat klare und einfache Strukturierung, ist leicht anwendbar• Sehr effizient bei bekannten und konstanten Anforderungen
Diesen Vorteilen stehen einige Nachteile gegenüber:• Missverständnisse und Spezifikationsfehler fallen erst spät auf und verursachen hohe
Kosten in der Fehlerbehebung
1 http://de.wikipedia.org/wiki/Wasserfallmodell
4
Abbildung 2.1: Vorgehensmodelle
Vorgehensmodelle
Klassische Methoden Agile Methoden
Wasserfallmodell
Spiralmodell
VModell
Extreme Programming
Scrum
Pragmatic Programming
2 Klassische und agile Methoden der Softwareentwicklung
• Der Prozess ist unflexibel gegenüber Änderungswünschen des Kunden• Dieses Modell kann zu inhaltlicher Veralterung bei großen Projekten, mit sehr langer
Laufzeit führen
Die Begriffe Iteration und Inkrement in der Softwareentwicklung werden oft frei und austauschbar benutzt. Sie sind jedoch nicht Synonyme. Iterative Entwicklung verbessert das Produkt, macht Fortschritte durch mehrere Verfeinerungen. Das ganze Projekt wird nicht nach dem klassischen Wasserfallmodell auf einmal definiert, sondern in kleinere Iterationen geteilt. Unter Iterationen werden die einzelnen Schritte verstanden, die in jeder beliebigen Folge wiederholt werden können (Abbildung 2.2).
Allerdings müssen dann alle nachfolgenden Schritte auch wiederholt werden. Jede Iteration liefert ein stabiles, getestetes und abgeschlossenes System. Nach jeder Iteration sollte dann die Abnahme des Produktes mit dem Kunden erfolgen, um die gestellten Anforderungen anzupassen. Inkrementelle Entwicklung baut und liefert Software an eine ProduktionsUmgebung als eine Reihe von kleinen und regelmäßigen Releases mit erweiterter Funktionalität. In jedem Folgerelease wird dem ersten Release eine weitere Funktionalität hinzugefügt, bis mit dem letzten das Gesamtsystem realisiert ist. Der Gedanke der iterativinkrementellen Softwareentwicklung wurde in einer Vielzahl von Vorgehensmodellen umgesetzt. Bei einer inkrementellen Softwareentwicklung erfolgt die Entwicklung der Software schrittweise, der komplette Entwicklungszyklus wird dazu mehrfach iterativ wiederholt. Als Beispiel für die iterativinkrementelle Entwicklung kann das Spiralmodell dienen. Bei diesem Modell werden einzelne Phasen des Wasserfallmodells zyklisch wiederholt. Jede Windung der Spirale steht für eine Phase des Prozesses.2 Das Spiralmodell bietet eine höhere Flexibilität für das Projektmanagement als die meisten anderen Vorgehensmodelle. Eine weitere Steigerung bietet hier das agile Vorgehen.
2 http://de.wikipedia.org/wiki/Spiralmodell
5
Abbildung 2.2: Ablauf einer iterativen Entwicklung (Quelle: [MunzSoergel07])
Feedback Feedback1. Iteration
Entwicklung für gegebene Anforderungen
2. IterationEntwicklung für
gegebene Anforderungen
3. IterationEntwicklung für
gegebene Anforderungen
1. Veröffentlichung 2. Veröffentlichung 3. Veröffentlichung
2 Klassische und agile Methoden der Softwareentwicklung
2.3 Agile Methoden der Softwareentwicklung
Agile Softwareentwicklung basiert auf den iterativinkrementellen Vorgehensmodellen. Ziel der agilen Softwareentwicklung ist es, den Entwicklungsprozess zu optimieren. Agile Modelle stellen die Funktionsfähigkeit der Software ins Zentrum der Softwareentwicklung. Dies ist aber nur dann möglich, wenn die traditionelle Denkweise bei der Softwareentwicklung geändert wird. In der agilen Softwareentwicklung werden folgende Begriffe benutzt:3
• Die agilen Werte bilden das Fundament der agilen Softwareentwicklung und wurden als „Agiles Manifest“ formuliert.
• Agile Prinzipien basieren auf den agilen Werten und bilden Grundsätze für die agile Arbeit.
• Agile Methoden oder Praktiken sind konkrete Verfahren während der Softwareentwicklung, die sich auf die Werte und Prinzipien stützen.
• Der agile Prozess ist die Zusammenfassung aller angewandten Methoden und dient der agilen Softwareentwicklung.
2.3.1 Das agile Manifest
Im Jahre 2001 trafen sich führende Vertreter der agilen Softwareentwicklungsbewegung und einigten sich auf das folgende Manifest als Grundlage aller agilen Methoden:
3 http://de.wikipedia.org/wiki/Agile_Softwareentwicklung
6
Abbildung 2.4: Das agile Manifest (Quelle: [AgileManifesto])
Wir entdecken bessere Möglichkeiten für die Entwicklung von Software, indem wir es tun und anderen dabei helfen.
Mit dieser Arbeit bewerten wir:
Individuen und Interaktionen vor Prozessen und Tools Funktionierende Software vor einer umfassenden Dokumentation Zusammenarbeit mit dem Kunden statt Vertragsverhandlungen
Reaktion auf Veränderungen ist wichtiger als einen Plan zu befolgen
Obwohl auch die Dinge auf der Rechten ihren Wert haben, schätzen wir die auf der Linken höher ein.
Abbildung 2.3: Agile Begriffe
Werte
Prinzipien
Prozess
Methode
Methode
2 Klassische und agile Methoden der Softwareentwicklung
Dies könnte mit anderen Worten folgendes bedeuten:1. Qualifikation der Mitarbeiter und ihre Zusammenarbeit sind die wichtigsten Faktoren
für ein erfolgreiches Projekt und werden höher bewertet als Prozesse und Werkzeuge.2. Vom Anwender wird die funktionsfähige Software beurteilt und nicht die umfassende
Dokumentation. Die Fortschritte im Projekt werden durch die fertige und funktionierende Software beurteilt.
3. Ein Vertrag gilt als Grundlage für die Zusammenarbeit. Aber nur gemeinsam mit dem Kunden kann wirklich gebrauchsfähige Software entwickelt werden.
4. Im Verlauf eines Entwicklungsprozesses ändern sich sehr oft die Anforderungen und Rahmenbedingungen. Die Entwickler müssen darauf schnell reagieren können.
Diese vier Werte bilden das Fundament der agilen Softwareentwicklung und verdeutlichen die Abgrenzung zu den traditionellen Methoden. Diese Werte müssen aber in der täglichen Arbeit auch tatsächlich umgesetzt werden. Dabei können die agilen Prinzipien helfen.
2.3.2 Prinzipien
Agile Prinzipien basieren auf den agilen Werten und bilden Handlungsgrundsätze, die zwischen Handlungsoptionen entscheiden helfen. Von Autoren des agilen Manifestes wurden zwölf Prinzipien formuliert:
1. Unsere höchste Priorität ist die Zufriedenheit der Kunden durch frühzeitige und kontinuierliche Lieferung hochwertiger Software.
2. Veränderte Anforderungen sollten immer positiv aufgenommen werden, selbst wenn sie sich erst spät in der Entwicklung zeigen. Agile Verfahren nutzen Änderungen zum Wettbewerbsvorteil des Kunden.
3. Funktionierende Software muss regelmäßig geliefert werden, innerhalb weniger Monate, wobei der kürzeren Zeitspanne eindeutig der Vorzug zu geben ist. Im Rahmen der Softwareentwicklung bedeutet der Prototyp ein funktionsfähiges Produkt, das bereits vor der Entwicklung des endgültigen Softwareprodukts vorliegt.
4. Geschäftsleute und Entwickler müssen während des gesamten Projekts täglich zusammenarbeiten. Erstellung der Anforderungen erfolgt im Dialog mit dem Auftraggeber und den Benutzern.
5. Das Projekt wird durch einzelne motivierte Personen aufgebaut. Die Mitarbeiter sollten eine entsprechende Umgebung und Unterstützung erhalten, um eine hochwertige Arbeit zu erbringen.
6. Die effizienteste und effektivste Methode zur Informationsübermittlung für und innerhalb eines Entwicklungsteams besteht in der direkten Kommunikation.
7
2 Klassische und agile Methoden der Softwareentwicklung
7. Funktionierende Software ist das wichtigste Maß für den Fortschritt. Zur Planung gehört die Kontrolle, d.h. das möglichst lückenlose Messen des Entwicklungsfortschritts am Plan.
8. Agile Prozesse fördern nachhaltige Entwicklung. Die Sponsoren, Entwickler und Benutzer sollten in der Lage sein, ein gleich bleibendes Tempo beibehalten zu können.
9. Ständige Aufmerksamkeit gegenüber technisch hervorragender Qualität sowie gutem Design verbessert die Agilität.
10. Schlichtheit ist die Kunst, die Menge der nicht geleisteten Arbeit zu maximieren.11. Die besten Architekturen, Anforderungen und Designs entwickeln sich in Teams, die
sich selbst organisieren.12. Die Teams müssen in regelmäßigen Abständen darüber beraten, wie sie noch effekti
ver arbeiten und ihr Verhalten entsprechend anpassen können.
2.3.3 Methoden und Prozesse
Während die Werte und Prinzipien das „Warum“ beschreiben, erläutern Methoden oder Praktiken das „Wie“ des Modells. Agile Methoden sind konkrete an Agilität ausgerichtete Verfahren während der Softwareentwicklung, die sich auf die Werte und Prinzipien stützen.
Die Methoden sind dann agil, wenn sie:• Iterative und inkrementelle Vorgehen nutzen• Lösungsorientiert sind • Positive Einstellung zu Veränderungen haben• Enge Kundenzusammenarbeit bieten• Häufige Rückkopplungen haben
Der agile Prozess ist ein auf Agilität ausgerichteter Softwareentwicklungsprozess, der überwiegend auf agile Methoden zurückgreift. Ziel des agilen Prozesses ist, die Entwicklung für alle Beteiligten effektiver und vorteilhafter zu gestalten. Es gibt eine Vielzahl von agilen Prozessen, die sich zahlreicher agiler Methoden bedienen. Zu den bekanntesten zählen unter anderem Scrum, eXtreme Programming (XP), Feature Driven Development (FDD) und Pragmatic Programming.
Extreme Programming ist das populärste unter den agilen Prozessen und wurde von Kent Beck aus seiner Sicht erfolgreichsten agilen Praktiken zusammengestellt. Es wurden insgesamt 5 Werte, 14 Prinzipien und 24 Praktiken definiert und deren Zusammenspiel beschrieben, wie Abbildung 2.5 zeigt.
8
2 Klassische und agile Methoden der Softwareentwicklung
Folgende Rollen werden in XP benutzt:• Die Entwicklergemeinde ist für die Programmierung, die Aufwandsschätzungen und
das Design verantwortlich.• Der Kunde schreibt und priorisiert die Anforderungen.• Der Projektleiter verfolgt den Entwicklungsaufwand.• XPCoach unterstützt das Team bei der Einhaltung der Praktiken.
Alle in XP definierten Praktiken müssen möglichst unverändert und als Ganzes angewendet werden. Die Entwicklung wird in Iterationen von etwa zwei Wochen geteilt. Jede Iteration wird ausgehend von den Erfahrungen der vorigen Iteration geplant.
Der zweite bekannteste agile Prozess ist Scrum. Er ist ein allgemeiner Managementrahmen für beliebige Projekte. Der ScrumProzess definiert folgende Rollen:
• Product Owner ist für die Formulierung, Auswahl und Priorisierung der Anforderungen zuständig.
• Das Team ist für die Umsetzung der Anforderungen verantwortlich.• Scrum Master unterstützt Product Owner und das Team bei der Durchführung des
Projektes und hilft bei konkreten Problemen.
9
Abbildung 2.5: XP Komponenten
Team Entwicklung Kunde Management
Programmieren in Paaren
Räumlich zusammen sitzen
Testgetriebene Entwicklung
Komplettes Team
Informative Arbeitsumgebung
Retrospektiven
Fortlaufende Integration
Iterationsplanung
Tägliches Meeting
Energiegeladene Arbeitsumgebung
TimeboxingKunde vor Ort
Akzeptierte Verantwortung
Ausdauerndes Tempo
Benutzergeschichten
Iterationsplanung
Kurze Releasezyklen . . .
Einfachheit Kommunikation Feedback Mut Respekt
Praktiken
Werte
Prinzipien Menschlichkeit Selbstständigkeit Wirtschaftlichkeit Verbesserung Redundanz
Babyschritte Qualität Fluss Fehlschlag . . .
2 Klassische und agile Methoden der Softwareentwicklung
Die Projekterstellung hat folgenden Verlauf (Abbildung 2.6):1. Von allen Projektbeteiligten werden Anforderungen erstellt und im Product Backlog
gesammelt. 2. Aus diesen Anforderungen werden vom Product Owner eine geringe Menge für das
Sprint Backlog ausgewählt. Das Team schätzt die Aufwände.3. Die Entwicklung wird in 30 Tage dauernden Iterationen „Sprints“, unterteilt. Das
Team arbeitet in dieser Zeit das Sprint Backlog ab.4. Zur Abstimmung werden täglich DailyScrumMeeting von 15 Minuten durchgeführt,
wo jeder drei Fragen beantworten muss:• Was habe ich seit dem letzten Meeting getan?• Gibt es irgendwelche Probleme?• Was werde ich bis zum nächsten Meeting tun?
5. Zum SprintEnde wird von allen Projektbeteiligten ein SprintReviewMeeting durchgeführt, wo man das SprintErgebniss präsentiert. Daraus ergeben sich ggf. neue oder geänderte Anforderungen für das Product Backlog.
2.4 Klassische versus agile Methoden
In Tabelle 1 sind die wichtigsten Merkmale agiler und klassischer Methoden gegenübergestellt. Sie verdeutlichen noch einmal, wie sich der agile Ansatz vom traditionellen Ansatz abgrenzt.
10
Abbildung 2.6: Der Scrum – Prozess (Quelle: [ScrumMaster])
2 Klassische und agile Methoden der Softwareentwicklung
klassische Vorgehensweise agile Vorgehensweise
Planung die genaue Planung mit vorgeschriebe→ nen Ablaufplan
→ man kann aber nicht am Anfang schon alles vorhersehen
→ spätere Änderungen sind sehr schwer zu berücksichtigen
kurzfristige Planung, das gesamte Team→ erstellt zusammen die Pläne für die aktuelle und nächste Iteration
spätere Änderungen können leicht ein→ gebaut werden
Anforderungen stabile, am Plan orientierte Anforderun→ gen
→ können sich aber während der Projektlaufzeit ändern
instabile Anforderungen ändern sich→ nach jeder Iteration
Änderungen stellen kein Problem dar,→ können aber zu Chaos führen
Aufwandsschätzung wird von Experten geschätzt→ → es ist aber nicht immer gut abschätzbar
wie lange das Team für die Umsetzung braucht
jeder im Team schätzt selbst am Anfang→ jeder Iteration den Aufwand für seine Aufgaben
kleine Abschnitte kann man leichter→ schätzen
Team planorientierte Arbeit→ Aufgaben werden vom Projektleiter zu→
geteilt Aufgaben → können nicht immer optimal
verteilt werden
selbstorganisierendes Team→ Teammitglieder wählen sich die Funk→
tionen aus enge Zusammenarbeit und Kommuni→
kation im Team das Team muss erfahren und → hoch qua
lifiziert sein
Kunden wird nur bei der Anforderungserstel→ lung einbezogen
arbeitet in jeder Phase mit→ nach jeder Iteration werden dem Kun→
den neue Softwareversionen zur Verfügung gestellt
höhere Kundenzufriedenheit→ , aber Kunde hat oft mangelndes Fachwissen
Dokumentation umfangreiche und detaillierte → wird nicht sehr großer Wert gelegt→
Projektgröße große Teams und große Projekte→ kleine Teams und kleine Projekte→
Hauptziel hohe Sicherheit in der Entwicklung → schnelle und regelmäßige Ergebnisse,→ zufriedene Kunden
Tabelle 1: Klassische versus agile Methoden
11
3 Agile Webentwicklung
3 Agile Webentwicklung
3.1 Grundlagen der Webentwicklung
Die Menschen steigen immer bewusster auf die neue Webbasierte Technologien um. Wir prüfen unsere EMails im Web, verwenden OnlineBanking, sehen Videos und Fotos an, kommunizieren mit Menschen auf der ganzen Welt über den Browser. Deshalb gewinnen die WebAnwendungen immer mehr an Bedeutung. Man kann eine WebAnwendung wie folgt definieren:„Eine WebAnwendung ist ein ComputerProgramm, das auf einem Webserver ausgeführt wird, wobei eine Interaktion mit dem Benutzer ausschließlich über einen Webbrowser erfolgt. Hierzu sind der Computer des Benutzers (Client) und der des Dienstanbieters (Server) über ein Netzwerk wie das Internet oder über ein Intranet miteinander verbunden, so dass die räumliche Entfernung zwischen Client und Server unerheblich ist.“1
Eine WebAnwendung wird vom Benutzer im Browser gestartet und damit wird ein HTTPRequest an den Webserver gesendet (Abbildung 3.1). Der Webserver nimmt die Anfrage entgegen und übergibt sie an die Webanwendung. Daraufhin wird der HTMLQuellcode einer Webseite generiert und als eine HTTPResponse zurück an den Browser geschickt.
WebAnwendungen haben gegenüber der klassischen Software viele Vorteile. Sie funktionieren auf jeder Plattform, die einen Browser hat. Im Gegensatz zu herkömmlicher Software braucht eine WebAnwendung keine zusätzlichen Installationen auf den Computer des Benutzers, was die Konformität von WebAnwendungen gewaltig erhöht und einen hohen Grad an PlattformUnabhängigkeit ermöglicht. Veränderungen an WebAnwendungen können schnell und nur einmal auf dem Webserver hinzugefügt werden.
1 http://de.wikipedia.org/wiki/Webanwendung
12
Abbildung 3.1: Datenfluss bei einer Webanwendung
Serverseite
Webserver
Clientseite
Webbrowser Webanwendung
Datenbank
HTTPRequest
HTTPResponse
CGI, fastCGI
3 Agile Webentwicklung
Die Entwicklung von WebAnwendungen kann sowohl client als auch serverseitig erfolgen. Bei der clientseitigen Webentwicklung ist die direkte Interaktion mit dem Benutzer wichtig. Dies kann die Reaktion auf die Maus, die direkte Überprüfung von Eingabedaten vor Übertragung zu einem Server sein. Zu clientseitigen Techniken zählen HTML, CSS, JavaScript, FlashTechniken, Ajax. Mit diesen Techniken können aus Sicherheitsgründen keine Datenbankzugriffe mehr benutzt werden.
Die serverseitige Entwicklung ist viel komplexer, da hier die Datenbankanbindungen verwendet werden. Einerseits wurden in diesem Bereich die Programmiersprachen wie Perl, Python oder Ruby für die Webentwicklung eingesetzt. Andererseits wurden ganz spezielle Techniken für Webentwicklung wie PHP, JSP usw. eingesetzt.
Durch die große Anzahl von Sprachen, steigende Anzahl von WebAnwendungen und deren Komplexität wurde die Entwicklung von dynamischen WebAnwendungen immer komplizierter, aufwendiger und umfangreicher. So ist es nicht verwunderlich, dass für die moderne serverseitige Webentwicklung eine Technologie gebraucht wurde, die nicht nur die Entwicklung beschleunigt, sondern die Wartung von WebAnwendungen erleichtert. Die Lösung erfolgte in Form von WebFrameworks, die eine Technologie für die agile serverseitige Webentwicklung darstellt.
Wie auch bei der agilen Softwareentwicklung wird in dem Bereich der agilen Webentwicklung mit WebFrameworks großer Wert auf Stabilität, Performance, Einfachheit, Erweiterbarkeit, Wiederverwendbarkeit, Veränderbarkeit und Testbarkeit der WebAnwendung gelegt. Performance spielt dabei eine besondere Rolle, da der Benutzer einer Webanwendung eine kürzere Antwortzeit erwartet. Bei Änderungen in den Anforderungen sollen diese leicht und mit wenig Aufwand eingespielt werden.
3.2 Agile Web Applikation Frameworks
Wer sich mit der modernen agilen Entwicklung von dynamischen WebAnwendungen beschäftigt, sollte ein Web Applikation Framework in Betracht ziehen. Ein Framework (Entwicklungsrahmen) ist ein Programmiergerüst, das einen Rahmen zur Verfügung stellt, innerhalb dessen ein User eine Anwendung erstellt. Ein Framework besteht aus einer Menge von zusammenarbeitenden Klassen, die einen wieder verwendbaren Entwurf für eine bestimmte Klasse von Software darstellen.
13
3 Agile Webentwicklung
In der Regel gibt ein Framework die Architektur der Anwendung vor. Das Framework steuert und nutzt eine registrierte, konkrete Implementierung des Programmierers. Bei einer Klassenbibliothek werden lediglich Klassen und Funktionen benutzt. Man spricht von einer Inversion of Control (Umkehrung der Steuerung). Damit das Framework den Kontrollfluss der Anwendung und die Schnittstellen für die konkreten Klassen definieren kann, müssen vom Programmierer die konkreten Klassen festgelegt, erstellt und registriert werden. Frameworks sind meist domainenspezifisch bzw. auf einen bestimmten Anwendungstyp beschränkt, da das Ziel eines Frameworks die Wiederverwendung eines bestimmten architektonischen Musters ist und diese Muster nicht ohne Rücksicht auf eine konkrete Anwendungsdomaine entworfen werden können.
Ein Web Applikation Framework ist ein SoftwareFramework, das zur Unterstützung der Entwicklung von dynamischen Webseiten, WebApplikationen und WebServices dient. Ein WebFramework vereinfacht die Entwicklung, Wartung und Verbreitung von WebAnwendungen und stellt dem Entwickler eine Basis zur Verfügung, die sich um häufig wiederkehrende Aufgaben kümmert [WikiWAF09]. Die meisten heutigen WebFrameworks unterstützen bereits die agile Webentwicklung. Als bekanntes Beispiel für das erste WebFramework dieser Art kann Ruby on Rails dienen. Ausgehend von den Werten, Prinzipien und Methoden der agilen Softwareentwicklung wurden die wichtigsten Grundprinzipien der agilen Webentwicklung formuliert, die jedes WebFramework enthalten muss, das sich als „agile“ bezeichnet.
3.3 Prinzipien agiler Webentwicklung
In diesem Abschnitt werden allgemeine Prinzipien dargelegt, die sich in einem Bereich der agilen Webentwicklung anwenden lassen.
3.3.1 MVCArchitektur
Eine allgemein anerkannte Architektur für agile WebFrameworks ist die ModellViewControllerArchitektur oder MVC. Die MVCArchitektur bezeichnet ein Architekturmuster, das die Entwicklung einer Software in drei voneinander relativ unabhängigen, getrennten Schichten darstellen soll. Ziel des Musters ist es, die Daten, Funktion und Layout voneinander zu trennen, um die spätere Änderung oder Erweiterung der einzelnen Komponenten zu erleichtern (Abbildung 3.2).
14
3 Agile Webentwicklung
Die Aufgabe des Modells ist die Bereitstellung, Verarbeitung, Speicherung und die Sicherstellung der Validität der Programmdaten. Der View stellt die Benutzerschnittstelle dar. Hier steht alles, was mit der Darstellung der dem Modell entstammenden Daten zu tun hat. Seine Aufgabe besteht in der Formatierung der Daten des aktuellen Modells zu einer geeigneten Darstellungsform. Der View enthält keine Funktionalität um das Modell zu ändern. Der Controller übernimmt die Koordination zwischen Modell und View und enthält die Logik einer Software. Er fordert die Daten des Modells an und leitet sie an einen View weiter, der sie darstellt. Er empfängt zudem Daten aus einem View und leitet sie kompetent an das Modell weiter.
3.3.2 Konvention über Konfiguration
Konvention über Konfiguration oder „Convention over Configuration“ bedeutet, dass die großen Konfigurationen im weitesten Sinne vermieden werden müssen. Der Entwickler muss sich nicht auf die Konfigurationsdatei, sondern auf die Arbeit selbst konzentrieren, was zur Entlastung und Beschleunigung seiner Arbeit führt. WebAnwendungen sollen sich nach bestimmten Konventionen richten, anstatt Standardeinstellungen in Konfigurationsdateien vorzugeben. Es existieren verschiedene Konventionen wie die Benennung von Datenbanken und Tabellen (Namenskonvention), Benutzung von Fremdschlüsseln und anderen. In diesen Fällen muss Ruby on Rails nicht extra konfiguriert werden. Natürlich kann jede Konvention jederzeit geändert oder neu konfiguriert werden, aber bei jeder Abweichung muss man mit höherem Konfigurationsaufwand rechnen. Viele moderne WebFrameworks nutzen diesen Ansatz. Jedes Framework hat seine eigenen Konventionen. Ein gutes Beispiel für die Realisierung dieses Prinzips sind Ruby on Rails und GrailsFrameworks.
15
Abbildung 3.2: MVCArchitektur
Browser
Controller
View
Modellruft auf
aktualisiert
informiert über Änderungen
DB
3 Agile Webentwicklung
3.3.3 DRYPrinzip
Die Anforderungen zum Projekt können sich während der Entwicklung ändern. Der gewählte Algorithmus funktioniert nicht mehr oder der Kunde hat seine Anforderungen geändert. Dies führt dazu, das die Information in einem System geändert oder neu formuliert werden muss, was zu Wiederholungen im System führen kann.
DRYPrinzip steht für Don't Repeat Yourself „wiederhole dich nicht". Jede Information im System muss nur einmal programmiert oder beschrieben werden. Das schließt im Idealfall Quelltexte, Datenbankschemata, Tests und Dokumentationen ein. Je mehr es Vervielfältigungen in einem System gibt, desto größer ist der Raum für die Fehler. Je mehr Orte gleiche Informationen haben, desto schwieriger wird es eine Änderung durchzuführen.
Es gibt verschiedene Gründe, die zu Wiederholungen führen können [PragProg03]:• Erzwungene Wiederholungen
Dieselbe Information wird in verschiedenen Formen benötigt und dadurch dupliziert, z.B. ein Datenbankschema wird durch eine Klasse wiedergespiegelt.
• Unabsichtliche WiederholungenAus Versehen oder aus Fehlern im Entwurf bemerkt man nicht, dass die Information sich wiederholt.
• Wiederholungen aus UngeduldWiederholen, weil es einfacher scheint. Wenn man z.B. eine Funktion benötigt, die einer existierenden ähnelt, dann versucht man oft das Original zu kopieren und zu modifizieren, statt die Originalfunktion flexibler zu machen, um für beides verwendet werden zu können.
• Wiederholungen durch mehrere EntwicklerWenn mehrere Entwickler an einem Projekt arbeiten, kann es dazu kommen, dass die verschiedenen Entwickler dieselbe Information im System wiederholen.
Als Beispiel für die Einhaltung des DRYPrinzips kann die DatenbankKonfigurationsdatei dienen. Um eine Verbindung zu einer Datenbank herzustellen, braucht man gewöhnlich die Anmeldeinformation wie z.B. einen Benutzernamen, ein Passwort, den Namen der Datenbank mit der man arbeiten will. Diese Informationen werden für jede Datenbankanfrage benutzt. Bei mehreren Anfragen wird die Anmeldeinformation im Quellcode mehrmals wiederholt. Wenn man den Benutzernamen oder das Passwort ändern will, muss man diese Information überall im Quelltext suchen und ersetzen. Es wäre eine bessere Idee die Verbindungsinformation in einer einzigen Datei zu speichern. Man muss dann nur eine einzelne Datei ändern. Das ist es, was dem DRYPrinzip entspricht.
16
3 Agile Webentwicklung
3.3.4 Objektrelationales und URLMapping
Objektorientierte Entwicklung arbeitet mit Objekten als Instanzen von Klassen. Um die Objekte aus der objektorientierten Welt in relationale Datenbanken zu speichern wird ein objektrelationales Mapping oder ORM benutzt:
• eine Tabelle wird zu einer Klasse zugeordnet• jeder Datensatz ist dabei eine Tabellenzeile und wird zu einem Objekt der jeweiligen
Klasse zugeordnet• ein Attribut eines Datensatzes wird zu einem Attribut des Objekts zugeordnet
Diese Kapselung erlaubt einen unproblematischen Zugriff auf die Daten in relationalen Datenbanken in objektorientierten Umgebungen. URLMapping definiert wie WebFrameworks URLs interpretieren. Manche WebFrameworks setzen dabei auf die implizite und manche auf die explizite URLKonfiguration. Bei der expliziten Konfiguration einer Anwendung wird eine extra URLKonfigurationsdatei angelegt, welche diesen Vorgang beschreibt. Wenn eine Adressanfrage eines Clients auf einen Ausdruck aus der Datei passt, so wird die entsprechende Aktion aufgerufen und die Webseite geladen. Trifft dies nicht zu, so wird eine Fehlerseite generiert. Eine solche Art von URLKonfiguration wird z.B. in Django realisiert. Andere WebFrameworks gehen häufig den Weg der impliziten URLAbbildung über Verzeichnisse und Funktionsnamen. Dies bedeutet, dass der Aufruf konkreter Controller oder Aktionen aus den URLs ermittelt wird.
3.3.5 CreateReadUpdateDeletePrinzip
Bei den meisten WebAnwendungen ist die Arbeit mit Datenbanken ein Muss. Datensätze müssen ständig erstellt, angezeigt, geändert und gelöscht werden. Solche Datenbankzugriffe müssen sehr oft programmiert werden und können recht aufwendig sein. Diese Datenbankoperationen werden oft mit dem Begriff CRUD (CreateReadUpdateDelete) bezeichnet. CRUD hat folgende Bedeutung: Create steht für „einen neuen Datensatz erstellen“, Read für „einen Datensatz lesen“, Update für „einen vorhandenen Datensatz ändern“ und Delete für „einen Datensatz löschen“. Anhand des Datenbankschemas werden für jedes Modell entsprechende Controller und Views erstellt, die das Erzeugen, Anzeigen, Bearbeiten und Löschen von Datensätzen ermöglichen und als Grundgerüst für die weitere Entwicklung benutzt werden können. Damit ist kein LowLevelQuellcode notwendig um schon am Anfang eine laufende Version der Anwendung zu sehen. Man kann mit den Kunden schon an einem laufenden System Anforderungen, Ablauf und Wünsche erörtern. Diese Technologie minimiert dem Entwickler den Arbeitsaufwand und erlaubt sofort mit dem Kern der Applikation zu beginnen.
17
3 Agile Webentwicklung
3.3.6 KISSPrinzip
Ursprünglich stammt die Bezeichnung von der Abkürzung des Satzes “Keep It Simple and Stupid” (Halte es einfach und leicht verständlich). KISSPrinzip besagt, dass die Entscheidungen und Lösungen eines Problems möglichst einfach gehalten werden sollen. Man muss nicht das Problem verkomplizieren, sondern einfache, leicht verständliche Lösungen des Problems nehmen. Je komplizierter ein Sachverhalt dargestellt wird, umso schwieriger wird es für alle Beteiligten, damit zu arbeiten.
3.3.7 AjaxUnterstützung
Ajax ist eine Technik für die Erstellung von interaktiven WebAnwendungen.2 Die Absicht ist es, dass der Inhalt der Webseite bei einer Kommunikation mit dem Server aktualisiert wird, ohne die komplette Seite neu zu laden. Aufgrund der Komplexität der AjaxProgrammierung in JavaScript, gibt es zahlreiche JavaScriptFrameworks, die ausschließlich mit AjaxUnterstützung arbeiten. WebFrameworks müssen JavaScriptFrameworks integriert haben, damit hoch interaktive und leistungsfähige AjaxAnwendungen erstellen werden können. Zu den bekanntesten Toolkits zählen: Prototype, jQuery, Dojo.
3.3.8 Testgetriebene Entwicklung
Durch die MVCArchitektur besteht eine WebAnwendung aus mehreren Teilen, die miteinander kommunizieren. Änderungen an einer Stelle können zu Konsequenzen an anderen Stellen führen. Je komplexer eine Anwendung ist, desto schwieriger ist es, die Ursachen für Fehler zu finden. Deshalb wird in der agilen Webentwicklung sehr großer Wert auf die testgetriebene Entwicklung3 von Anwendungen gelegt. Dabei werden Tests nicht wie gewöhnlich am Ende des Projekts durchgeführt, sondern vor dem eigentlichen Code programmiert um jede Funktionalität der Anwendung zu testen. Im Test wird überprüft, ob der Quellcode der Anwendung der Annahme entspricht. Der Testcode wird so lange verbessert, bis er alle Tests bestanden hat. Fügt man später neuen Code hinzu, wird dieser keine Fehler in altem, bereits getestetem Code verursachen. In der agilen Webentwicklung sind drei Arten von solchen Tests bekannt, UnitTests, IntegrationTests und FunctionalTests.
2 http://de.wikipedia.org/wiki/Ajax_(Programmierung)3 http://de.wikipedia.org/wiki/Testgetriebene_Entwicklung
18
3 Agile Webentwicklung
3.4 Auswahl der WebFrameworks
Fast für jede Sprache gibt es ein oder mehrere WebFrameworks. Ein WebFramework ist nur dann gut, wenn es dem Entwickler Zeit und Arbeit einspart. Man muss zuerst entscheiden, welches WebFramework für das Projekt gebräuchlich ist und ob es überhaupt Vorteile bringt. Dabei spielen die subjektiven Einschätzungen der Entwickler eine sehr große Rolle. Da die Auswahl an WebFrameworks riesig ist, wurde aus der gesamten Menge eine kleine Gruppe für die nähere Betrachtung ausgewählt. Anschließend werden, aufgrund der Bewertung drei WebFrameworks für die Entwicklung der Beispielanwendung ausgesucht.
Die Microsoft .NET oder Javabasierten Web Applikation Frameworks wie JSF, ApacheStruts, Tapestry und Cocoon werden ausgeschlossen, da sie sehr umfangreich und vielschichtig sind. Sie erfordern einen hohen Lernaufwand und benötigen einen hohen Umfang an Konfiguration und Einrichtung. Dadurch wurde die Auswahl auf die Scriptsprachen wie PHP, Python, Groovy und Ruby beschränkt.
Aus jeder Sprachgruppe wurden die am weitesten verbreiteten WebFrameworks für die nähere Betrachtung ausgesucht. Um die Eingriffe in den Quellcode problemlos zu ermöglichen, muss das WebFramework einer Open Source Lizenz unterliegen. Das WebFramework sollte nach Möglichkeit ein FullStack Framework sein. Dies bedeutet, dass alles, was man benötigt, in der Box sein sollte. Keine komplexe Installationen und Konfigurationen von Bibliotheken oder Komponenten ist somit erforderlich. Die verschiedenen Schichten sollten reibungslos zusammenpassen und funktionieren.
Die Gruppe der WebFrameworks wird auf allgemeine Kriterien wie Einfachheit, Performance, Skalierbarkeit, Erweiterbarkeit, Veränderbarkeit, Stabilität, PluginAuswahl und die Dokumentation untersucht. Die Bewertungen bleiben in gewissem Maße subjektiv und werden vor allem auf allgemeinen Informationen aufgebaut, die zu jedem WebFramework zur Verfügung stehen und aus den Vergleichstest, aus den verschiedenen im Web verfügbaren Quellen herangezogen werden.
Das Ziel dieser Auswahl ist, die drei am besten geeigneten WebFrameworks für die Entwicklung einer Beispielanwendung zu finden, für die dann der präzise Vergleich durchgeführt wird. Alle ausgewählten WebFrameworks basieren auf der MVCArchitektur, unterstützen objektrelationales Mapping, sowie zu einem gewissen Grad weitere Prinzipien der agilen Webentwicklung (Tabelle 2).
19
3 Agile Webentwicklung
WebFramework Einfachheit Performance Skalierbarkeit Veränderbarkeit Stabilität Plugins Auswahl Dokumentation
PHP WebFrameworks
cakePHP +++ + + ++ ++ +++ +
Symphony ++ + + ++ ++ +++ ++
Zend ++ + + ++ ++ +++ +++
Python WebFrameworks
Django ++ +++ +++ ++ ++ ++ ++
Turbo Gears ++ +++ +++ ++ ++ + ++
Pylons + +++ +++ ++ + + ++
Java(Groovy) WebFramework
Grails ++ + +++ +++ +++ +++ +
Ruby WebFramework
Ruby on Rails +++ ++ +++ +++ +++ +++ +++
+ schlecht ++ mittel +++ gut
Tabelle 2: Übersicht von WebFrameworks
PHPFrameworks sind bedeutende neue Entwicklungen der letzten zwei Jahre. Generelle Vor und Nachteile von PHPFrameworks stehen in direktem Zusammenhang mit der PHPSprache. Sie haben zwei große Vorteile gegenüber den anderen WebFrameworks. Für PHP gibt es eine große Menge von Erweiterungen, Bibliotheken und Modulen. Die Sprache ist sehr verbreitet und somit ist der Einarbeitungsaufwand begrenzt. PHP an sich ist aber keine objektorientierte Sprache, obwohl in der PHP5 viele Nachteile beseitigt wurden. Außerdem hat PHP immer noch Sicherheitsprobleme. Weiterhin spricht gegen die Auswahl eines PHPFrameworks die Tatsache, dass eine Vielzahl von PHPFrameworks die Philosophie von Ruby on Rails übernommen haben. Mehr zum Vergleich von den drei weit verbreiteten PHPFrameworks Zend, Symfony und CakePHP, kann auf der IBMWebseite [PHPFr2] nachgelesen werden.
Es sind mittlerweile mehrere hundert verschiedene PythonFrameworks für die verschiedensten Bereiche bekannt. Dies liegt vor allem an der Einfachheit und Lesbarkeit von PythonCode, der guten Erweiterbarkeit und an der Realisierung spezieller Anforderungen. Zu den Vorteilen von PythonWebFrameworks zählt, dass die Anwendung in relativ kurzer Zeit implementiert werden kann. Python verfügt außerdem über viele Module. Sehr wichtig ist, dass bei allen drei vorgestellten WebFrameworks eine besonders gute Dokumentation vorhanden ist. Als Nachteil kann die große Auswahl von PythonWebFrameworks dienen. Daher fällt es sehr schwer sich für ein WebFramework zu entscheiden. Im Internet kann der Vergleich aus den Quellen wie etwa [PyWebFr] und [PyWebFr2] herangezogen werden.
20
3 Agile Webentwicklung
Grails ist ganz neu unter den WebFrameworks und wurde von Ruby on Rails inspiriert. Grails wurde sehr oft als „Ruby on Rails für die JavaWelt“ bezeichnet. Es baut auf der dynamischen Scriptsprache Groovy auf und ist höchst kompatibel mit der JavaPlattform. Darüber hinaus ist Grails in der Lage, die Vielfalt aller vorhandenen JavaTechnologien wie Ant, Hibernate, Spring oder SiteMesh zu nutzen, was dem WebFramework eine Stabilität verleiht, die auch Java auszeichnet. Vorteilhaft ist es auch, dass Groovy direkt in JavaBytecode übersetzt wird und perfekte Integration zur Java Plattform und zu bestehenden JavaAnwendungen hat. Als Nachteile kann der Mangel an Informationsmaterial sowie die schlechte Performance des GrailsWebFrameworks gesehen werden.
Derzeit ist Ruby on Rails, oft Rails genannt das dominierende WebEntwicklungFramework für Ruby. Auch außerhalb der RubyCommunity, gilt es als ein „Klassiker“ unter agilen WebFrameworks der neuesten Generation, das hohe Produktivität bietet. Das Framework verfügt über eine gute Dokumentation und schnell wachsende Community. Nachteile von Ruby on Rails sind, dass immer noch viel zu wenig Webhosting zur Verfügung stehen. Außerdem ist Ruby keine Universalsprache und ist nur für WebAnwendungen konzipiert.
Anhand der Tabelle 2 und der aufgelisteten Vor und Nachteile wurde die drei WebFrameworks Ruby on Rails, Django und Grails ausgewählt.
21
4 Eingesetzte Technologien
4 Eingesetzte Technologien
Um Verständnis für die Funktionsfähigkeit der verwendeten Software zu vermitteln, sind in diesem Kapitel die verwendeten WebFrameworks kurz beschrieben werden. Zu jedem Framework ist die grundlegende Funktionsweise und das dahinter liegende Konzept herausgearbeitet und dargestellt. Ziel ist es, für jedes WebFrameworks die Besonderheiten bei der Umsetzung von agilen Prinzipien kurz zu erläutern.
4.1 Ruby on Rails
4.1.1 Einführung in Ruby on Rails
Ruby on Rails auch Rails genannt, wurde von David Heinemeier Hansson im Juli 2004 veröffentlicht und seit dem verbreitet sich das WebFramework sehr schnell. Rails ist nicht nur das erste WebFramework für Ruby, sondern hat viele neue Konzepte in Bereich Webentwicklung mitgebracht. Rails basiert auf der dynamisch typisierten Programmiersprache Ruby, die im Jahr 1995 von Yukihiro Matsumoto entwickelt wurde. Ruby ist eine objektorientierte, dynamische Sprache, die leicht zu verstehen und zu lernen ist. Den Großteil seiner Fähigkeiten hat Rails der Sprache Ruby zu verdanken.
Rails verkörpert fast alle Prinzipien der agilen Webentwicklung:• Rails hat ein gut strukturiertes ModellViewControllerKonzept. Einzelne Kompo
nenten werden mit Hilfe des SubFrameworks erstellt. ActiveRecord steht für Modelle, ActionView für Views und ActionController für Controller bereit.
• Konvention über KonfigurationPrinzip wurde per Default so konfiguriert, dass die Anwendung ohne große Konfigurationen auskommt.
• Das DRYPrinzip wird in Rails fast in allen Bereichen umgesetzt. Als Beispiel kann die Verbindung einer Klasse und einer Datenbanktabelle dienen.
• Datenverwaltung (CRUD) wird in Rails durch so genanntes Scaffolding realisiert. Scaffolding erzeugt basierend auf dem Datenbankschema entsprechende Controller und Views, was schon zu einem früheren Zeitpunkt eine erste lauffähige Version zu liefern ermöglicht.
• Testgetriebene Entwicklung wird in Rails durch drei Arten von Tests unterstützt: UnitTest testet die Funktionalität auf der Modellebene, FunctionalTest testet die Funktionalität von Controllern und von Views, der IntegrationTest sorgt dafür, dass die einzelnen Komponenten in einer Anwendung richtig zusammenspielen.
22
4 Eingesetzte Technologien
4.1.2 MVCArchitektur mit Rails
Rails basiert auf einer MVCArchitektur und bietet für jede Komponente ein SubFramework. Die drei wichtigsten Komponenten heißen: ActionController, ActiveRecord und ActionView, die unabhängig voneinander eingesetzt werden können. Diese Komponenten kommunizieren miteinander folgendermaßen (Abbildung 4.1):
• Der vom Client gesendete Request wird vom HTTPServer entgegengenommen und an den Dispatcher weitergeleitet.
• Die Aufgabe des Dispatchers ist die Weiterleitung von Anfragen an den dafür zuständigen Controller.
• Der Controller in Rails basiert auf dem ActionControllerFramework. Der Controller kommuniziert mit dem ActiveRecordFramework, welches die Verbindung zu den Datenbanktabellen bereitstellt.
• Im Anschluss wird die Anfrage an einen anderen Controller weitergeleitet oder es wird die Antwort generiert.
• Die Antwort wird mit Hilfe von ActionView aus HTMLTemplates erzeugt.
23
Abbildung 4.1: Bestandteile von Rails (Quelle:[RabWeb])
CRUD
Daten
Anfrage Daten
lädt
Dispatcher
Active Record
DBMySQL,
PostgreSQL
Action ControllerAction View
Action Mailer
sendet
liefert
XML, HTML, CSS, JavaScript
zeigt
FastCGIWeiterleitung an
WebServerWEBRick, Apache,
LightTPD
Request
HTTP, RSS, SOAP
Browser
4 Eingesetzte Technologien
4.1.3 ActiveRecord
Das Modell ist mit einem SubFramework ActiveRecord realisiert und repräsentiert das M im MVCParadigma. ActiveRecord ist für die Verbindung zwischen DomainObjekten und der Datenbank zuständig. Jede ModellKlasse erbt von der ActiveRecord::Base Klasse. Das Modul nutzt das objektrelationale Mapping (ORM) und ist immer nur mit einer Datenbanktabelle verbunden. Eine Datenbanktabelle wird automatisch über Namenskonventionen hergestellt, indem als Tabellenname die Pluralform des Klassennamens verwendet wird. Das Framework führt ein Wörterbuch dazu, das auch um deutsche Namen erweitert werden kann. Diese Zuordnung zwischen Modell und Datenbanktabelle erfolgt dabei ohne große Konfiguration. Dadurch wird die Einhaltung des „Konvention über Konfiguration“ Prinzips sichergestellt. Eine Instanz einer Klasse repräsentiert genau eine Datenzeile in der Tabelle, die Tabellenspalten stellen die Attribute der Klasse dar, dadurch wird das andere wichtige Prinzip der agilen Webentwicklung DRYPrinzip eingehalten.
Ein Modell wird in Rails mit Hilfe von script/generate erstellt:
Dem Generator wird als erster Parameter der Name des Generators mitgeteilt, in diesem Fall ist es model und als zweiter Parameter wird der Name der zu erzeugenden Klasse übergeben. Nach diesem Befehl werden das leere Model student.rb selbst, ein UnitTest student_test.rb und die Migrationsdatei in den dafür vorgesehenen Verzeichnissen erstellt.
Das Migrationsskript wird in Rails dafür verwendet um die Datenbankänderungen während der Entwicklung durchzuführen. Jede Migration implementiert zwei Methoden, up und down. Die upMethode ermöglicht die Datenbank um eine Stufe zu aktualisieren, die downMethode dagegen macht die Änderungen um eine Stufe rückgängig. Der Dateiname enthält eine Versionsnummer oder das Datum und den Klassennamen der Migration, zum Beispiel create_students. Die generierte Migration kann folgendermaßen aussehen:
24
$ ruby script/generate model student
Quellcode 1: Migrationsdatei
1 class CreateStudents < ActiveRecord::Migration 2 def self.up 3 create_table :students do |t| 4 end 5 end 6 7 def self.down 8 drop_table :students 9 end 10 end
4 Eingesetzte Technologien
Bei einer Migrationsdatei handelt es sich um eine Klasse, die von ActiveRecord::Migration erbt. Die downMethode ist bereits bei der Erstellung vollständig. In der upMethode fehlt aber noch die Definition der einzelnen Spalten. Die upMethode kann nach der Erstellung um die Modellattribute erweitert werden:
In diesem Beispiel wird durch den Befehl create_table eine Tabelle students mit einzelnen Attributen angelegt. Eine Attributdefinition enthält den Attributnamen und den Typ, weitere Parameter sind optional. Zusätzlich zu den genannten Spalten wird automatisch eine Spalte id für Primärschlüssel erzeugt. Mit dem Befehl rake db:migrate können definierte Tasks ausgeführt und eine Tabelle students mit einzelnen Spalten angelegt werden. Um eine bestimmte Datenbankversion wieder herzustellen, wird der rakeBefehl mit der Migrationsnummer als Parameter aufgerufen:
In den meisten Anwendungen stehen die Tabellen in einer gewissen Beziehungen1 zueinander. Assoziationen werden in Rails in der Datenbank mit Hilfe von Fremdschlüsseln definiert und gleichzeitig in einem Modell beschrieben. Das ActiveRecordSubFramework übernimmt auch die Validierung von Objekten. Die Validierung wird immer durchgeführt, wenn ein Objekt in die Datenbank gespeichert werden soll. Schlägt die Prüfung fehl, wird eine entsprechende Fehlermeldung ausgegeben.
4.1.4 ActionController
Das Modul ActionPack fasst die beiden Module ActionController und ActionView zusammen. ActionController übernimmt den Teil des Controllers und steht für das C im MVCPattern. Der Controller steuert den Datenfluss zwischen Modell und View, in dem er den HTTPRequest empfängt, bearbeitet und in Form eines View an den Client zurücksendet.
1 http://de.wikipedia.org/wiki/Kardinalit%C3%A4t_(Datenbanken)
25
rake db:migrate VERSION=1
Quellcode 2: Definition einer Modellklasse
1 class CreateStudents < ActiveRecord::Migration 2 def self.up 3 create_table :students do |t| 4 t.string :firstname 5 t.integer :matnr 6 t.text :address 7 ... 7 end
4 Eingesetzte Technologien
Der RailsController ist eine RubyKlasse, die von der gemeinsamen Basisklasse ActionController::Base erbt. Der Controller wird mit Hilfe von script/generate erzeugt, wo als erster Parameter controller und als zweiter der Name des Controllers übergeben wird:
Alternativ kann man den ScaffoldingGenerator nutzen, bei dem das gesamte CRUD2Gerüst aus dem Controller und zugehörigen Views erstellt wird. Dem Generator wird als erster Parameter das Modell und als zweiter Parameter der Controller übergeben:
Um die verschiedenen Aufgaben auszuführen werden im Controller Aktionen definiert, die nichts weiteres als die Methode des Controllers sind. Zu einem Controller gibt es in der Regel mehrere Aktionen und mehrere Views. Zu jeder Aktion gibt es jeweils ein View. Es werden automatisch folgende Aktionen in jedem Controller erstellt: index, show, edit, create, update, destroy. Für jede dieser Aktionen, außer destroy, wird jeweils ein View erzeugt.
Als Ergebnis bei der Ausführung einer Aktion wird ein View geliefert oder eine weitere Aktion ausgeführt. Per Konvention über Konfiguration wird von jeder Aktion ein View ausgeliefert, der den gleichen Namen wie die Aktion trägt. Wenn der Name des darzustellenden Views von dem Namen der Aktion abweicht, wird die renderMethode benutzt:
Die gleiche Methode wird verwendet, wenn der View sich in einem anderen als dem ViewVerzeichnis des Controllers befindet. Ein Controller kann auf RequestParameter über die paramsMethode zugreifen, die ein Hash mit den gesamten Parametern des Request liefert. Datenaustausch vom Controller zum View läuft über die im Controller definierte Instanzvariable, die dann den gesamten Views automatisch zur Verfügung stehen. Dies verdeutlicht Abbildung 4.2. In diesem Beispiel wird die Instanzvariable @stwork im Controller students in der Aktion show definiert und enthält eine Studentenarbeit aus der Datenbanktabelle, die anhand einer id ausgesucht wurde. Der zugehörige show.rhtmlView greift dann auf die Variable mit normalem RubyCode zu und zeigt die Angaben zur Studentenarbeit an.
2 Create Read Update Delete
26
$ ruby script/generate controller student
$ ruby script/generate scaffold student student
Quellcode 3: renderMethode
1 def show_studentwork 2 @stwork=Stwork.find(params[:id]) 3 render :action => 'show' 4 end
4 Eingesetzte Technologien
Der Request kann auf eine andere Aktion weitergeleitet werden um dort die Verarbeitung fortzusetzen. Dies wird durch den redirect_toBefehl gewährleistet.
Im folgenden Beispiel löscht die Aktion destroy_studentwork eine Studentenarbeit und leitet den Request zur showAktion weiter, die im gleichen Controller definiert ist:
Die Weiterleitung kann natürlich auch zu einer Aktion aus einem anderen Controller erfolgen. Man muss dann einen Parameter mit dem Namen des Controllers hinzuzufügen:
Da HTTP ein zustandsloses Protokoll ist, wird sehr oft eine Session benutzt, die es ermöglicht, die Objekte zwischen den einzelnen Anfragen zwischenzuspeichern. Ein Objekt kann mit Hilfe der sessionMethode gespeichert werden:
Ein Objekt kann aus einer Session folgendermaßen abgefragt werden:
27
def new session[:username]= 'Admin' end
@user=User.find(session[:user_id])
Abbildung 4.2: Datenaustausch vom Controller zum View
app/controllers/students_controller.rb class StworksController < ApplicationController def show @stwork = Stwork.find(params[:id]) end end
app/views/stworks/show.rhtml <html> ... Art: <%= @stwork.artofwork %> Title: <%= @stwork.title %> </html>
Quellcode 4: redirect_toBefehl
1 def destroy_studentwork 2 stwork=Stwork.find(params[:id]) 3 stwork.destroy 4 redirect_to :action => 'show', :id => student 5 end
redirect_to :controller =>'students',:action =>'show', :id =>@student
4 Eingesetzte Technologien
4.1.5 URLKonfiguration
Rails nutzt so genanntes Routing, d.h. dass der Aufruf eines konkreten Controllers oder einer Aktion aus der URLs ermittelt wird. Dieses Verhalten wird in der route.rbDatei definiert. Angenommen, die Webseite steht unter http://localhost:3000/studentwork/ students/edit/21 (Abbildung 4.3).
Aus dem Pfad ordnet Rails den einzusetzenden Controller und die Aktion zu. Es wird z.B. der Controller students und die Aktion edit aufgerufen und dieser als idParameter die Zahl 21 übergeben. Die Aktion edit wird dann aus dem paramsHash über den idParameter auf den übergebenen Wert zugreifen. Dies bedeutet, dass die Eingaben zum Student mit id=21 bearbeitet werden können.
4.1.6 ActionView
ActionView steht für das V in MVC und ist für die Darstellung der Daten zuständig. Alle Views werden im app/viewsVerzeichnis in einem Unterverzeichnis abgelegt, das so wie der Controller heißt. Normalerweise trägt ein View den Namen der Aktion. Dadurch erkennt Rails automatisch welcher View am Ende einer Aktion geladen werden muss. In Rails wird zwischen drei Arten von Templates unterschieden: RHTMLTemplates, RXMLTemplates und RJSTemplates.
28
Abbildung 4.3: RailsRouting
URL: http://localhost:3000/studentwork/students/edit/21 der Name der Anwendung
der Name des Controllers aufrufende Methode id
Routingdatei: config/routes.rb ActionController::Routing::Routes.draw do |map| map.connect ':controller/:action/:id' end params[controller] => student params[action] => „edit“ params[id] => „21“
Controller: students_controller.rb cass StudentsController < ApplicationController def edit @student = Student.find(params[:id]) end end
4 Eingesetzte Technologien
In einem RHTMLTemplate wird der dynamische RubyCode in die HTMLSeite hinzugefügt und die Dateien erhalten die Endung *.rhtml oder ab Rails 2.0Version *.html.erb. Dieses Verfahren nennt man Embedded Ruby (ERB).
In ERBTemplates werden einige spezielle Tags benutzt:• RubyAusdrücke stehen zwischen <%= RubyCode%>, wo RubyCode ausgewertet
und anschließend ausgegeben wird. Es wird zum Beispiel der Vorname des Studenten ausgegeben werden:
• RubyAnweisungen <% RubyCode %> werden ausgeführt:
RXMLTemplates haben die Endung *.rxml und werden mit Hilfe von Ruby XMLCode erzeugt. RJSTemplates sind so genannte RubyJava Script Templates und haben die Endung *.rjs. Mit Hilfe von diesen Templates wird aus RubyBefehlen JavaScriptCode generiert. Das erlaubt zum Beispiel das Aktualisieren beliebiger Bereiche einer Webseite mittels Ajax. Im Sinne von MVC und der Trennung der Verantwortlichkeit soll HTML nicht mehr RubyCode enthalten als nötig und keine Programmlogik im Template verwenden. Deshalb bietet das SubFramework ActionView bereits einige HelperMethoden, wodurch der HTMLCode kürzer und übersichtlicher wird. Diese Umfassen die Erzeugung von Formularelementen3, das Formatieren von Texten4 sowie Zahlen5 und URLHelper6.
Es ist auch möglich eigene HelperMethoden zu entwickeln. Bei der Generierung eines Controllers wird automatisch ein HelperModul erstellt. In dem Modul definierte Hilfsmethoden stehen automatisch für alle Templates des Controllers zur Verfügung. Alle HelperModule sind im app/helpersVerzeichnis ausgelagert und tragen den Namen des Controllers mit dem Suffix _helper. Die Methoden, die innerhalb der HelperModule definiert sind, enthalten gewöhnlich die für die Templates eines Controllers spezifische Methoden und sind für die anderen Controller nicht sichtbar.
3 http://api.rubyonrails.org/classes/ActionView/Helpers/FormTagHelper.html4 http://api.rubyonrails.org/classes/ActionView/Helpers/TextHelper.html5 http://api.rubyonrails.org/classes/ActionView/Helpers/NumberHelper.html6 http://api.rubyonrails.org/classes/ActionView/Helpers/UrlHelper.html
29
<%= @student.firstname %>
<% if current_user.login == "admin" %> … <% end %>
4 Eingesetzte Technologien
Mehrseitige WebAnwendungen enthalten immer dieselben Elemente, die auf den meisten Webseiten vorkommen. Bestimmte Teile der Webseiten wie Fuß oder Kopfzeile haben ein einheitliches Erscheinungsbild. Um diese Elemente nicht jedes Mal aufs Neue zu erstellen, können sie in die LayoutDatei unter app/views/layout ausgelagert werden. Ein Layout, das für die gesamte Anwendung gültig ist, muss als application.html.erb bezeichnet werden. Eine LayoutDatei kann auch automatisch einem Controller zugeordnet werden, indem sie den gleichen Namen wie der Controller trägt. Das Layout kann einem Controller auch explizit über den Aufruf der layoutMethode zugeordnet werden. Die LayoutDatei hat mehrere Platzhalter, an deren Stellen der dynamische Inhalt aus den Templates oder aus dem Partial eingefügt werden soll. Zum Beispiel an der Stelle von content_for_layout soll dann der Quelltext aus den Templates eingefügt werden:
Ein weiteres interessantes und nützliches Konzept in Rails sind Partials. Dabei geht es darum, dass Teile der RHTMLDatei, wie zum Beispiel Formulare, in eine separate Datei ausgelagert werden. Dies kann zur Einhaltung des DRYPrinzips dienen. Die Nutzung von Partials ist nur dann sinnvoll, wenn ein unbestimmter Abschnitt des View öfter vorkommt. Der Name des Partials beginnt per Konvention immer mit einem Unterstrich. Abbildung 4.4 veranschaulicht die Verwendung von Partials in einer WebAnwendung:
30
Abbildung 4.4: Verwendung von Partials
main_layout.rhtml
Main
Header
Footer
main_layout.rhtml …
<%= render :partial => 'header' %><%= render :partial => 'main' %>
<%= render :partial => 'footer' %>_footer.rhtml
_header.rhtml
_main.rhtml
Quellcode 5: LayoutDatei
1 <html> 2 <div class="header"> 3 <%= render :partial => 'header' %> 4 </div> 5 <div class="main"> 6 <%= @content_for_layout %> 7 </div> 8 <div class="footer"> 9 <%= render :partial => 'footer' %> 10 </div> 11 </html>
4 Eingesetzte Technologien
4.2 Django
4.2.1 Einführung in Django
Django wurde ursprünglich für eine OnlineZeitungen entwickelt und ist in der Programmiersprache Python geschrieben. Dabei war es wichtig die straffen Deadlines einzuhalten und die hohen Anforderungen in OnlineRedaktionen zu erfüllen. Das Framework wurde erst im Jahr 2005 unter einer freien Lizenz zugänglich gemacht. Benannt wurde es nach dem JazzGitarristen Django Reinhard. Mit seinen Prinzipien weicht Django etwas von anderen WebFrameworks ab.
Django verkörpert und stellt Prinzipien der agilen Webentwicklung wie folgt dar:• MVC Konzept wird in Django als MTV (ModelTemplateView) umgesetzt.• Django hat einen integrierten objektrelationalen Mapper, der ein Datenmodell auto
matisch in einer Datenbank verwaltet.• DRYPrinzip ist besonders gut bei Datenbankabstraktionen einsetzbar, bei denen aus
dem in Python geschriebenen Datenmodell automatisch eine Zugriffsschicht für den Datenbankzugriff definiert wird.
• Bei Django wird kein einfaches CRUDGerüst bereitgestellt, dafür aber ein umfangreiches und professionelles AdminInterface. Dieses wird auf Basis des Datenmodells automatisch generiert und ermöglicht die Administration aller Inhalte und Benutzer.
• Django vertritt das Prinzip geringer Kopplung zwischen den einzelnen Komponenten, was einen einfachen Austausch und Erweiterungsmöglichkeit um neue Elemente ermöglicht. Es ist z.B. problemlos möglich, Applikationen in verschiedenen Projekten zu verwenden, ohne den Code anpassen zu müssen.
• Django liefert flexible und gut aussehende URLs mittels regulärer Ausdrucke und setzt dabei auf eine explizite URLKonfiguration einer Anwendung. Damit der View angezeigt werden kann, müssen URLs explizit mittels regulärer Ausdrücke in der urls.py vorgenommen werden. DRYPrinzip ist dabei auf keinen Fall vernachlässigt, da die Änderungen immer noch an einer Stelle vorgenommen werden. Die URLKonfiguration funktioniert aber nicht automatisch, es wird nur das abgebildet, was vom Benutzer in die urls.py Datei eingegebenen wurde.
• Die TemplateEngine trennt den Programmcode vom Inhalt. Darüber hinaus unterstützt es die einfache Verschachtelung von Templates über eine Vererbung.
• In Django werden Projekte und Applikationen definiert. Als Projekt wird eine Website als Ganzes bezeichnet, Applikationen dagegen realisieren die Funktionalität des Projekts. Es wird aber in beiden Fällen keine Ordnerstruktur wie z.B. bei Rails erstellt, alle Dateien müssen von Benutzer hinzugefügt werden.
31
4 Eingesetzte Technologien
4.2.2 MTVArchitektur mit Django
Wie viele andere WebFrameworks verwendet Django auch das MVCKonzept. Es ist aber kein „klassisches“ MVCKonzept, es wird mehr von einer MTVArchitektur gesprochen. Das Modell definiert die Struktur der Daten und bietet eine Schnittstelle für den Zugriff auf die in der Datenbank gespeicherten Daten. Die Views wurden in Templates umbenannt und übernehmen die eigentliche Anzeige von Daten. Der Controller heißt in Django View, da dieser die Schnittstelle zwischen Client und Django realisiert und die Logik der Webanwendung übernimmt. Sie kümmert sich um die Aufbereitung von Daten und greift auf die Modelle zurück um deren Daten zu verändern. Die vom Benutzer abgefragten Daten werden von dem View ermittelt, verarbeitet und dann weiter an das Template übergeben (Abbildung 4.5).
Django bearbeitet die Anfragen folgendermaßen (Abbildung 4.6):• Nachdem der Entwicklungsserver mit dem Befehl python manage.py runserver gest
artet wird, importiert Django als erste die settings.pyDatei, wo sich die wichtigsten Konfigurationsparameter des Projektes befinden.
• Die vom Browser gesendete Anfrage wird vom HTTPEntwicklungsserver entgegengenommen, durch ModPythonHandler in ein HttpRequestObjekt verwandelt und an das RequestMiddleware weitergeleitet.
• Der Parameter ROOT_URLCONFIG in der settings.pyDatei legt fest, welche URLKonfigurationsdatei für die Webanwendung benutzt werden soll. Diese Datei wird geladen und die geforderte URL mit den Musteradressen in der URLKonfigurationsdatei verglichen.
32
Abbildung 4.5: Bestandteile von Django
Weiterleitung an
WebServer (Apache)
Request
View
Datenbank
Anfrage Daten
Template Model
Abfrage VeränderungAusgaben Eingaben
Browser
4 Eingesetzte Technologien
• Wenn die Übereinstimmung gefunden wurde, wird ein mit der Musteradresse verbundener View angefordert und ein HttpRequestObjekt als erster Parameter an den View übergeben.
• Als Antwort gibt der View ein HttpResponseObjekt zurück.
4.2.3 Modell
Die Datenbankstrukturen erfolgen über Klassendefinitionen, aus denen das WebFramework die erforderlichen SQLAnweisungen für die Erstellung der Datenbanktabellen ableitet. Analog werden diese Klassen genutzt, um automatisiert SQLOperationen für die Datenpflege zu erzeugen. Darauf aufbauend generiert Django gleichfalls HTMLOberflächen zur Administration und Pflege der Daten. Für jedes Objekt bzw. jede Tabelle in der Datenbank muss eine Modellklasse definiert werden, die von der Basisklasse models.Model im Paket django.db abgeleitet wird. Damit das Modell in die Datenbank geschrieben wird, muss Django die Datenbank abgleichen. Dies wird mit dem Befehl python manage.py syncdb vorgenommen. Django legt für jede Modellklasse eine eigene neue Tabelle an, die jedes Attribut der Klasse als eine Spalte darstellt. Die Namen der Spalten entsprechen dabei den Attributnamen. Außerdem wird für jede Klasse, die von dem Modell erbt, eine Spalte namens id hinzugefügt, die als Integer mit autoincrement definiert ist.
33
Abbildung 4.6: Ablauf von Django Request und Response (Quelle: [DjB])
4 Eingesetzte Technologien
4.2.4 Die URLKonfiguration
In Django kann man selbst angeben, über welche Adresse ein bestimmter Teil der Seite erreichbar sein soll. Für diese Aufgabe wird eine extra URLKonfigurationsdatei urls.py angelegt, welche diesen Vorgang beschreibt. Dabei ist jeder View einzeln ansprechbar und kann mit einer beliebigen Adresse verknüpft werden. Jeder Adresse in dieser Datei wird ein View zugeordnet (Quellcode 6).
Der Aufbau der urls.pyDatei ist sehr einfach. Es wird eine Variable namens urlpatterns definiert, die in einer patternsInstanz eine Liste mit allen Adressen des Projekts enthält, wo jede Adresse aus zwei Tupel besteht. Der erste Eintrag ist ein so genannter Regex, der eine Adresse über einen regulären Ausdruck konfiguriert. In dem zweiten Eintrag wird ein verknüpfter View aufgerufen.
Wird nun eine Seite des Projekts im Browser aufgerufen, prüft Django alle Adressen der Reihe nach für alle Einträge der urlpatternsListe, ob der reguläre Ausdruck auf den relativen Pfad der geforderten Adresse passt. Ist dies der Fall, wird der View oder die Funktion aufgerufen, die durch den String im zweiten Eintrag verknüpft wird und die Suche nach einer passenden URL wird abgebrochen. Trifft keines der Muster auf die gegebene Adresse zu, so wird eine Fehlerseite generiert. Mehr dazu ist in der DjangoDokumentation zu finden.7
4.2.5 Automatische Administrationsoberfläche
Django erstellt vollautomatisch aus den Modellklassen eine komfortable Administrationsoberfläche, sodass man von der lästigen Eigenimplementation verschont bleibt. Man muss nur kleine Änderungen an dem Datenmodell und der Konfiguration des Projekts vornehmen. In den INSTALLED_APPSBereich der settings.pyDatei muss die Applikation mit dem Namen django.contrib.admin eingefügt werden.
7 http://docs.djangoproject.com/en/dev/topics/http/urls/#topicshttpurls
34
Quellcode 6: URLKonfiguration
1 from django.conf.urls.defaults import * 2 3 urlpatterns = patterns('', 4 (r'^student/$', 'studentworkdj.students.views.index'), 5 (r'^studentwork/$', studentworkdj.studentwork.views.index), 6 (r'^students/logout/$', 'django.contrib.auth.views.logout'), 7 )
4 Eingesetzte Technologien
Anschließend werden die Änderungen in der Datei urls.py vorgenommen. Hier müssen einige Kommentarzeichen für angegebene Zeilen entfernt werden (Quellcode 7):
Als Letztes muss für jede Applikation eine weitere admin.pyDatei angelegt werden, in der die Modellklassen hinzufügt werden müssen, die administriert werden sollen. Als Ergebnis wird das StandardAdminInterface zur Verfügung gestellt.
Wenn man das Interface erweitern oder ändern möchte, muss man noch die ModelAdminKlasse hinzufügen, die die Darstellung eines Modells im AdminInterface steuert. Umfangreiche Informationen über die ModelAdminKlasse sind in der DjangoDokumentation zu finden.8
4.2.6 View
Wie bereits beschrieben wurde, enthalten die Views die gesamte Funktionalität einer Anwendung. Die Modelle und Templates werden dadurch verknüpft und entsprechende HTMLSeiten generiert. Ein View ist eine einfache PythonFunktion, die für die Darstellung von Daten im Browser zuständig ist. Die Funktion bekommt als ersten Parameter die Anfrage als Objekt, weitere Parameter können aus der URL extrahiert werden.
Die Views müssen nicht nur Objekte abrufen, sondern auch Templates rendern, welche die nötigen Variablen als Parameter vom View erhalten. Alle Views einer Applikation werden üblicherweise in der Datei views.py des Applikationsverzeichnisses abgelegt. Vor der Definition von Views müssen zuerst die benötigten Klassen importiert werden. Weitere Informationen zur Erstellung von Views kann man in der Dokumentation nachlesen.9
8 http://docs.djangoproject.com/en/dev/ref/contrib/admin/#refcontribadmin9 http://docs.djangoproject.com/en/dev/
35
Quellcode 7: AdminInterfaceKonfiguration in der urls.pyDatei
1 from django.conf.u rls.defaults import * 2 from django.contrib import admin 3 admin.autodiscover() 4 5 urlpatterns = patterns('', 6 # Uncomment this for admin: 7 (r'^admin/', include(admin.site.urls)), 8 ... 9 )
4 Eingesetzte Technologien
4.2.7 Template
Ein Template, das man auch Platzhalter nennt, generiert aus den übergebenen Daten eine entsprechende Ausgabe. Django nutzt für die Definition von Templates eine eigene Sprache, was es ermöglicht jeden beliebigen Ausgabedatentyp zu erzeugen. Bevor man aber mit Templates arbeiten kann, muss man den Pfad in der settings.pyDatei definieren, unter dem Django nach Templates suchen muss. Am einfachsten erstellt man einen Ordner in dem Projektverzeichnis, wo alle TemplateDateien des Projektes abgelegt werden können. Anschließend trägt man den Pfad in die settings.pyDatei ein:
Die Nutzung des TemplateSystem ist sehr einfach:• Das gesamte System wird von einem Untermodul django.template gekapselt. Als Ers
tes wird ein Template geladen und daraus ein TemplateObjekt erstellt.• Die Werte für das Template werden über einen so genannten Kontext übergeben. Der
Kontext ist eine Liste mit übergebenen Variablen mit dazugehörigen Werten.
Diese beiden Schritte übernimmt die Funktion render_to_response aus dem Modul django.shortcuts. Die Funktion lädt das Template, füllt den Kontext und liefert ein HttpResponseObjekt zurück. Der Funktion render_to_response wird noch ein zusätzliches Argument RequestContext aus dem Modul django.template übergeben. Das Argument enthält einen Kontext, der beim Rendern eines Templates benötigt wird. RequestContext fügt eine Reihe von Variablen zu dem Kontext hinzu wie HttpRequestObjekt oder Informationen über die aktuell angemeldeten Benutzer:
Als erstes Argument übernimmt die Funktion den Namen des Templates, in diesem Fall index.html. Als zweites Argument wird das so genannte Wörterbuch die Variable mit der Studentenliste übergeben und als drittes Argument wird ein RequestContextObjekt übergeben.
36
TEMPLATE_DIRS = ( "/home/helga/web/django_projects/studentworkdj/templates/", )
Quellcode 8: render_to_responseFunktion
1 from django.shortcuts import render_to_response 2 from django.template.context import RequestContext 3 ... 4 def index( request ): 5 student_list = Student.objects.all() 6 return render_to_response( 'index.html', 7 {'student_list':student_list}, 8 context_instance = RequestContext(request)) 9 ...
4 Eingesetzte Technologien
Templates können sowohl einfache HTMLElemente als auch spezielle Anweisungen der TemplateSprache enthalten. Spezielle Anweisungen kann man in zwei Gruppen einteilen, Variablenausgabe und TemplateTags. Der Wert von Variablen zum Beispiel wird in doppelten geschweiften Klammern ausgegeben. Die Liste aller Tags und umfangreiche Beispiele befinden sich in der DjangoDokumentation.10
Django nutzt so genannte TemplateVererbung. Es kommt sehr häufig vor, dass viele Seiten einer WebAnwendung das gleiche Grundgerüst aus Kopfzeile, Inhalt und Fußzeile besitzen. Dieses Grundgerüst kann man in einem zentralen Template auslagern und davon die konkret benötigten Templates ableiten. Änderungen müssen dann nur noch an einer einzigen Stelle durchgeführt werden, da sie sich auf alle abgeleiteten Templates auswirken.
Das Template in der Datei base.html enthält zum Beispiel das Grundgerüst der WebAnwendung. Mit dem Befehl {% extends "base.html" %} kann man ein anderes Template davon ableiten (Quellcode 9).
Alle CSS und JavaScriptDateien müssen dann auch nur in der base.htmlDatei definiert werden und stehen dann in allen abgeleiteten Dateien zur Verfügung:
Genaue Informationen zu abgeleiteten Templates sind in der DjangoDokumentation zu finden.11
10 http://docs.djangoproject.com/en/dev/ref/templates/builtins/?from=olddocs#builtintagreference11 http://docs.djangoproject.com/en/dev/ref/templates/builtins/?from=olddocs#templateinheritance
37
<link rel="stylesheet" type="text/css" href="/media/css/base.css"/> <script type="text/javascript" src="{{MEDIA_URL}}js/jquery.js"> </script>
Quellcode 9: Die Verbindung eines Templates
1 # base.html 2 <title> 3 {% block title %} Title{% endblock %} 4 </title> 5 {% block content %} Inhalt {% endblock %} 6 {% block footer %} Fußzeile {% endblock %} 7 8 # index.html 9 {% extends "base.html" %} 10 11 {% block title %} Hallo World {% endblock %} 12 {% block content %} <h1>Hallo World!</h1> {% endblock %}
4 Eingesetzte Technologien
4.3 Grails
4.3.1 Einführung in Grails
In der JavaWelt steht mit der Java EE eine unglaubliche Vielfalt an leistungsstarken und vielfältigen Technologien zur Verfügung. Obwohl diese um bewährte Frameworks wie Spring und Hibernate erweitert wurden, bleibt die Entwicklung von WebApplikationen mit der Java EE schwerfällig und komplex. Der Erfolg von Ruby on Rails hat nur noch deutlicher gemacht, dass es im JavaUmfeld einen Bedarf an einem System mit schnellem Feedback, hohen Änderungsmöglichkeiten und mit der Unterstützung von Web 2.0 Technologien gibt. Dies kann man nur mit dem Einsatz einer dynamischen Sprache erreichen. Für die JavaPlattform wurde Groovy als solch eine Sprache entwickelt. Daraufhin ist Grails im Jahre 2005 entstanden. Grails ist ein NextGenerationJavaWebEntwicklungsFramework, das große Zeit und Produktivitätsgewinne durch den Zusammenfluss mit einer dynamischen Sprache erzeugt, eine Konvention über KonfigurationPhilosophie, stark pragmatische SupportTools und eine agile Perspektive, gekennzeichnet von den besten neuen WebentwicklungParadigmen, bietet. Die Gründer waren Guillaume LaForge, Steven Devijver und Graeme Rocher. Zuerst wurde das Projekt „Rails“ genannt, da aber schon das Framework Ruby on Rails erschienen war, wurde das neue Framework in „Grails“ umbenannt. Grails hat viele Funktionen von Ruby on Rails geerbt, es gibt aber die Unterschiede, die sich aus dem Aufbau auf der JavaPlattform ergeben.
Grails verkörpert folgende agile Prinzipien:• Grails basiert auf einer MVCArchitektur, wo der Controller auf dem SpringFrame
work, das Modell auf Groovy ObjectRelationalesMapping (GORM) und View auf SiteMeshFramework basieren.
• Konvention über Konfiguration in Grails ermöglicht eine Vielzahl von Konventionen. Es wird z.B. eine vordefinierte Projektstruktur mit häufig anfallenden Konfigurationsdateien angelegt, der Typ von Klassen (Controller, Services, TagLibs) wird durch das Verzeichnis festgelegt, in dem die QuellcodeDatei liegt, ControllerKlassen sollten immer mit den Namen "Controller" enden.
• Durch GrailsCRUDFunktionalität wird die automatische Erzeugung eines Grundgerüstes ermöglicht.
• Die Testgetriebene Entwicklung wird durch JUnit unterstützt.• Die AjaxUnterstützung wird mit Hilfe von eingebauten JavaScriptFrameworks Pro
totype und Dojo geleistet. • Das GrailsFramework hat ein mächtiges PluginSystem, das sehr einfach zu benut
zen ist.
38
4 Eingesetzte Technologien
4.3.2 MVCArchitektur mit Grails
Grails fügt den JavaTechnologien kaum etwas hinzu, sondern verbindet eine Vielzahl von unterschiedlichen JavaFrameworks und Komponenten zu einer Einheit, die in einer JavaLaufzeitumgebung läuft. Das GrailsTeam hat sich für folgende Technologien entschieden: Groovy, Spring12, Hibernate13, SiteMesh14, Prototype15, Dojo16, JUnit17. Systemunabhängigkeit wird aufgrund der Java Virtual Maschine erreicht.
• Java EE/JDK dienen als Basis für die Webapplikation.• Spring dient als Verbindung der einzelnen Bausteine. Normalerweise ist eine Grails
WebApplikation eine Spring MVCApplikation.• Hibernate ist ein Standard für ObjektRelationalMapping in der JavaWelt, das für
die Entwicklung der Objekte aus dem DomainModell zuständig ist.• SiteMesh ist ein TemplateEngine, das für ein einheitliches Layout der Webapplikati
on sorgt.• Groovy ist eine dynamische Scriptsprache, die für die Implementierung des Domain
Modells, der Applikationslogik in den ControllerKlassen und für die dynamischen Anteile der Views zuständig ist.
12 http://de.wikipedia.org/wiki/Spring_(Framework)13 http://de.wikipedia.org/wiki/Hibernate_(Framework)14 http://en.wikipedia.org/wiki/SiteMesh15 http://www.prototypejs.org/16 http://www.dojotoolkit.org/17 http://www.junit.org/
39
Abbildung 4.7: GrailsKomponenten (Quelle: [JavaMag09])
JDK
SiteMesh
Java Virtual Machine
Java EE
Spring Hibernate
GroovyServices
Controller
Views/Templates Plugins
Grails
4 Eingesetzte Technologien
Eine typische Bearbeitung einer Anfrage im GrailsFramework stellt Abbildung 4.8 dar:
Eine Anfrage mit den übermittelten Parametern wird vom Browser zum Controller geschickt. Der Controller bearbeitet diese Anfrage, dabei kann er auf das zugrunde liegende Datenmodell mit Hilfe von GORM zugreifen. Die Antwort kann entweder unmittelbar im Controller ausgegeben oder an den View weitergeleitet werden. Damit der View weiß, welche Daten dargestellt werden sollen, übergibt der Controller ihm eine Referenz auf die ModellObjekte. Anschließend werden die Ergebnisse der Anfrage erstellt, mit Hilfe von GSPView verwertet und an den Browser zurückgeschickt.
4.3.3 Modell
Um aus den DomainModellen die entsprechenden Datenbanktabellen und Datenbankzugriffe zu generieren nutzt Grails ein Modul namens GORM Groovy Object Relational Mapper.18 GORM kann man als eine Abstraktionsschicht über Hibernate bezeichnen. Als Basis nutzt GORM eine vereinfachte Syntax von Hibernate und implementiert zusätzlich diverse eigene Zusatzfunktionen. Die direkte HibernateKonfiguration via XMLDateien kann jederzeit im Verzeichnis grailsapp/conf/hibernate zusätzlich vorgenommen werden. Eine Funktionalität von GORM ist die Validierung. Bevor man DomainObjekte in die Datenbank schreibt, überprüft man per Konvention, ob alle definierten Eigenschaften für das DomainObjekt vorhanden sind. Zu diesem Zweck benutzt Grails innerhalb von DomainKlassen einen so genannten constraintsBlock, in dem für jedes Property Bedingungen deklariert werden können.
18 http://www.grails.org/GORM
40
Abbildung 4.8: Bearbeitung einer Anfrage in Grails
Web Container Jetty HSQL DB
ModellRequest
View
Controller
Response Anfrage Daten
Browser
4 Eingesetzte Technologien
Der schnellste Weg, die DatenbankAbfragen zu erstellen, wird durch das Konzept der dynamischen Finder realisiert. Die dynamischen Finder sind eine präzise Art und Weise die Abfragen mit einer natürlichen und verständlichen Sprache zu realisieren. Der Name „dynamische Finder“ kommt von der Tatsache, dass die eigentlichen Methodennamen dynamisch aufgebaut werden können. Daraufhin kann eine Vielzahl von Methoden aufgebaut werden. Diese Methoden stehen für alle Eigenschaften einer DomainKlasse zur Verfügung. Die StworkKlasse verfügt zum Beispiel über Eigenschaften wie art und title. Diese können durch die findBy und findAllByMethode in der Form von "method expressions" verwendet werden. Eine ExpressionsMethode ist ein Methoden Ausdruck in GORM, der eine Prefixsuche, gefolgt von einem Ausdruck und der eine oder mehrere Eigenschaften vereint, benutzt:
Die Abbildung zeigt die Syntax zum Nachschlagen in dem stworkObjekt. Der logische UNDAusdruck in der Mitte ermöglicht die Suche mit beiden Argumenten durchzuführen. Dies könnte durch einen logischen ODERAusdruck ersetzt werden. Somit ist die Suche entweder nach einem Titel oder nach einer Art möglich.
Dynamische Finder unterstützen eine breite Palette von Komparatoren wie GreaterThan bzw. LessThan, Like, and Between. Zum Beispiel die Verwendung des LikeKomporators:
In dem obigen Beispiel wird in der ersten Abfrage nach allen Studentenarbeiten gesucht, die den Titel „Grails“ haben, während in der zweiten Abfrage aufgrund des LIKEKomparators, ein SQLPlatzhalter (%) hinzugefügt wird. Daraufhin werden alle Studentenarbeiten gesucht, die mit „Grails“ anfangen. Die StworkKlasse verfügt eigentlich über keine findAllByTitleLikeMethode. Grails schafft sie dynamisch mit der GroovyMetaClassKlasse.
Weitere Informationen zu GORM sind in der GrailsDokumentation nachzulesen.19
19 http://grails.org/doc/latest/guide/5.%20Object%20Relational%20Mapping%20(GORM).html
41
def results = Stwork.findAllByTitle("Grails") results = Stwork.findAllByTitleLike("Grails%")
Abbildung 4.9: Syntax des dynamischen Finders
DomainKlasse titleEigenschaft logisches UND erstes Argument
Stwork.findAllByTitleLikeAndArt(„Grails%“, „Diplomarbeit“)
dynamischer Finder Komporator artEigenschaft zweites Argument
4 Eingesetzte Technologien
4.3.4 Controller
Um Objekte einer Klasse anzulegen, zu verwalten, zu speichern, aufzulisten, zu verändern und zu löschen wird ein CRUDGerüst notwendig. Grails hat eine Standardlösung zu diesem Problem. Das Scaffolding generiert auf Basis der DomainKlassen sämtlichen Quellcode. Aufbauend auf einer bestehenden DomainKlasse erzeugt Grails automatisch Controller und Views für grundlegende CRUDFunktionen. Aktionen werden als Eigenschaften eines Controllers definiert und können über den Controller angesprochen werden.
Grails unterscheidet zwischen statischem und dynamischem Scaffolding. Beim statischen Scaffolding werden sichtbare Groovy und GSPDateien mit entsprechendem Sourcecode generiert. Das ist immer dann sinnvoll, wenn man danach den Code verändern möchte. Die statische Variante ist sehr nützlich, wenn man mit Anpassungen rechnen muss. Bei der dynamischen Variante werden die Funktionalitäten schrittweise erstellt. Wenn die Standardfunktionalität ausreicht, kann zunächst für die DomainKlasse ein Controller angelegt werden, in dem man dann die Eigenschaft scaffold auf true setzt. Die einzelnen Aktionen werden lediglich wenn nötig implementiert. Der Controller hat immer die Namensendung Controller und wird mit dem folgenden Befehl erstellt:
Jeder Controller hat eine Menge von Aktionen, die als Eigenschaften eines Controllers definiert werden und einer URI zugeordnet sind. Jede Aktion ist mit einem gleichnamigen View verbunden, d.h. dass nach der Ausführung der listAktion eine Liste mit Daten an den list.gspView weitergeleitet wird. Per Konvention wird in Grails für jede Aktion immer ein gleichnamiger View gerendert. Jeder Controller verfügt über eine Anzahl vordefinierter Eigenschaften, so genannte Scopes, in denen man Variablen speichern kann.
Dem Controller stehen zum Beispiel folgende Scopes zur Verfügung: session, request, params, flash usw. Der sessionScope ermöglicht die Zuordnung zu einem bestimmten Benutzer und verwendet in der Regel Cookies um eine Session mit einem Client zu assoziieren. Der requestScope ist ein RequestObjekt, der die Speicherung von Objekten für die aktuelle Anfrage erlaubt. Der paramsScope enthält ein Hash von eingehenden RequestParametern, der die Parameternamen auf Objekte referenziert. Wenn zum Beispiel student ein Objekt der DomainKlasse Student ist, dann würde params.student ein Objekt vom Typ Student referenzieren. Der flashScope ermöglicht es ein Attribut für die nächste Anfrage in einem temporären Speicher bereitzustellen. Er kann genutzt werden um den Benutzer über den Status von Aktionen zu informieren.
42
$ grails create-controller Student
4 Eingesetzte Technologien
Die einfachste Art ein ModellObjekt an den View weiterzuleiten, ist ihm die Instanz zurückzugeben:
Alle Parameter in Grails werden als Strings übergeben, deshalb ist es notwendig sie auf die Datenmodelle zu verweisen. Dies geschieht über die Zuweisung der Parameter an die Eigenschaft properties eines Modells. Unterscheiden sich die Namen der Aktion und des zugehörigen Views voneinander, so wird eine renderMethode benutzt:
Die redirectMethode ermöglicht die Weiterleitung an eine andere Aktion. Diese Methode kann auch optionalen Parameter nutzen:
4.3.5 View
Grundsätzlich kann man in Grails Views als Java Server Pages (JSP) oder als Groovy Server Pages (GSP) implementieren, die GroovyVariante GSP ist jedoch flexibler. GSP sind HTMLSeiten mit Platzhaltern und Anweisungen zur Darstellung der Daten im Browser. Sie basieren auf GroovyServlet und haben die Dateiendung ".gsp". Die GSPDateien befinden sich im grailsapp/viewsVerzeichnis und werden in der Regel entweder automatisch mit dem ScaffoldGenerator grails generateviews oder mit der RenderMethode render(view:"index") erstellt. Innerhalb jedes Controllers gibt es eine Konvention, die an Views weitergeleitet wird. Der korrespondierende View zur ControllerMethode show sollte zum Beispiel unter grailsapp\views\student liegen und show.gsp oder show.jsp heißen. Jedem View wird von einem Controller ein Modell übergeben, damit der View eine Reihe von Variablen für die Darstellung verwenden kann. GSP versucht so kompatibel wie möglich zu JSP zu bleiben, deshalb unterstützt es traditionelle JSPSkriptletBlöcke. GSP nutzt außerdem die eingebauten Tags, der bevorzugte Weg um GSPSeiten zu definieren. Alle eingebauten GSPTags beginnen mit dem Präfix g. Im Gegensatz zu JSP muss man aber nicht jede TagBibliothek importieren. Beginnt ein Tag mit g, wird er automatisch als ein GSPTag angenommen.
43
def studentInstance = new Student() studentInstance.properties = params return ['studentInstance':studentInstance]
def show = { def studentInstance = Student.get( params.id ) render(view:'ansicht',model:[studentInstance:studentInstance]) }
redirect(action:list) // einfache Weiterleitung redirect(action:list,id:studentInstance.id) //mit Parametern redirect(controller:"stwork",action:"list") //auf einen anderen Controller
4 Eingesetzte Technologien
Das Template wird zum Trennen der Views in wartbare und wiederverwendbare Blöcke eingesetzt. Grails verwendet die Konvention, indem ein Unterstrich vor dem Namen des Templates gesetzt wird um die Datei als Template zu identifizieren. Für das Layout ist in Grails außerdem das SiteMeshFramework verantwortlich. Layouts sind in dem layoutsVerzeichnis abzulegen. Ein typisches Layout hat normalerweise drei Platzhalter: layoutTitle gibt den Titel der Zielseite an, layoutHead gibt den Header der Zielseite an und layoutBody gibt dem bodyBereich die Zielseite an:
Um dem Layout den Views zuzuweisen, muss es im zugehörigen Controller mit der Zeile static layout = 'main' deklariert werden.
4.3.6 Die URLKonfiguration
Grails verwendet für das URLMapping die StandardKombination controller/action/id. Diese Konvention wird in der grailsapp/conf/UrlMappings.groovyDatei definiert. Die UrlMappingsKlasse enthält eine einzelne Eigenschaft mappings, die einem CodeBlock zugewiesen wird:
44
Quellcode 11: UrlMappings.groovyDatei
1 class UrlMappings { 2 static mappings = { 3 "/" (controller:'login', action:'auth') 4 "/$controller/$action?/$id?" {} 5 }
Quellcode 10: LayoutDatei
1 <html> 2 <head> 3 <title><g:layoutTitle default="Grails Beispielanwendung"/> 4 </title> 5 <g:layoutHead /> 6 </head> 7 8 <body> 9 <g:layoutBody /> 10 <g:render template="/footer" /> 11 </body> 12 </html>
5 Definition der Evaluierungskriterien
5 Definition der Evaluierungskriterien
In diesem Kapitel werden die wichtigsten Evaluationskriterien der WebFrameworks diskutiert. Die definierten Kriterien dienen als Grundlage für den Entwurf und die Implementierung der Beispielanwendungen. Das Ziel der Evaluierung ist die Prüfung, welches WebFramework sich am besten für die agile Softwareentwicklung im Bereich der Webentwicklung eignet. Als Evaluierungsobjekte werden in dieser Arbeit drei WebFrameworks und die damit entwickelten Beispielanwendungen dienen.
Zunächst werden die Evaluationskriterien der WebFrameworks herausgearbeitet und zu Kriteriengruppen zusammengefasst Die Kriterien sind aus Studien verschiedener Quellen entstanden. Es wurden objektive als auch subjektive Kriterien genutzt, die für die agile Webentwicklung relevant sind. Die Kriterien sind so ausgewählt, dass sie ermöglichen die agilen Grundprinzipien im Bereich der Webentwicklung zu überprüfen.
Als Zweites werden daraus die Anforderungen an die Beispielanwendungen formuliert und mit Hilfe der drei WebFrameworks implementiert. Durch das praktische Arbeiten mit den WebFrameworks sollte klar werden, wo die Stärken und Schwächen liegen und wie die definierten Anforderungen umgesetzt werden.
Der Umfang der Beispielanwendungen ist für alle drei WebFrameworks gleich definiert. Er wurde bewusst gering gewählt, um den zeitlichen Aufwand bei der Entwicklung überschaubar zu halten. Am Ende des Kapitel 7 befindet sich die Evaluierung und die Bewertung der WebFrameworks. Hier fließen die Ergebnisse der Implementierung und die eigenen subjektiven Einschätzungen des WebFrameworks während der Entwicklung ein.
Die Untersuchung der WebFrameworks wird für die einzelnen Kriterien durchgeführt. Es gibt viele Faktoren, die bei der Bewertung eines WebFrameworks wichtig sind. Die Kriterien, nach welchen die vorgestellten Ansätze evaluiert werden, werden nach ihrer Funktionalität und Wichtigkeit in fünf Kategorien gegliedert (Tabelle 3): FunktionaleKriterien, Dokumentation und ProjektCommunity, Support, Entwicklungseffizienz und sonstige Kriterien. Jede Kategorie erhält einen Wichtungsfaktor. Unter der Kategorie „Sonstige Kriterien“ werden die Kriterien hinzugefügt, die zu keiner anderen Kategorie passen und keine sehr hohe Priorität beim Vergleich haben.
Der Einfachheit halber wurde ein einheitlicher Wichtungsfaktor mehrerer Kriterien einer Kategorie zugeordnet.
45
5 Definition der Evaluierungskriterien
Kategorie Kriterien Wichtungsfaktor
K1 Funktionale Kriterien Datenbank und Modelle
0,3
Controller (Django:View)
Templates
URLRouting
DatenVerwaltung
BenutzerVerwaltung
K2 Dokumentation und ProjektCommunity
Dokumentation0,3
ProjektCommunity
K3 Support Installation
0,2
Entwicklungsprozess
AjaxUnterstützung
PluginSupport
DeploymentSupport und Webhosting
K4 Entwicklungseffizienz Implementierungszeit0,1
Codeeffizienz
K5 Sonstige Kriterien Programmiersprache
0,1Job Perspektiven
Security
0,3 sehr wichtig 0,2 wichtig 0,1 mäßig wichtig
Tabelle 3: Evaluierungskriterien
Für eine quantitative Beurteilung erfolgt die Bewertung in den einzelnen Kategorien durch die Noten (Tabelle 4):
Bewertung Bedeutung
1 sehr gut
2 gut
3 befriedigend
4 genügend
5 nicht genügend/nicht umgesetzt
Tabelle 4: Bewertung der Evaluierengskriterien
46
5 Definition der Evaluierungskriterien
Mit der folgenden Formel wird die Durchschnittsnote einer Kategorie bestimmt.
Kategorie=∑i=1
N
Kriteriumbewertungi
N
N ist die Zahl der Kriterien in einer Kategorie.
Da die Kriterien unterschiedliche Prioritäten und Wichtigkeit haben, werden die einzelnen Kategorien gewichtet. Das Gesamtergebnis der Evaluierung setzt sich aus den einzelnen Kategoriebewertungen mit den dazugehörigen Wichtungsfaktor zusammen:
Gesamtergebnis=∑j=1
M
Kategorie j×Wichtungsfaktor
M ist die Zahl der Kategorien.
47
6 Entwurf und Implementierung
6 Entwurf und Implementierung
In diesem Kapitel werden zuerst die Anforderungen an die Beispielanwendung definiert und anschließend erfolgt die eigentliche Umsetzung mit Hilfe der einzelnen WebFrameworks. Für jedes der drei WebFrameworks ist eine Implementierung der Beispielanwendung notwendig. Die im Kapitel 5 an die WebFrameworks definierten Kriterien, werden einem PraxisTest unterzogen. Die Realisierung erfolgte auf einem UbuntuGNU/LinuxSystem, Version 8.10.
6.1 Anforderungen an die Beispielanwendung
Unter Anforderungen versteht man gewünschte Ziele, die man bei der Entwicklung zu erreichen versucht. Sie bilden die Grundlage und den Ausgangspunkt für die eigentliche Entwicklung. In der Theorie und Praxis gibt es eine große Anzahl unterschiedlicher Anforderungsarten. Generell lassen sich Anforderungen in funktionale und nicht funktionale Anforderungen unterteilen. Im Rahmen dieser Implementierung begrenzt man sich auf die funktionalen Anforderungen. Funktionale Anforderungen beschreiben die Funktionalität der Software. Die Funktionalität besteht dabei insbesondere aus systeminternen Funktionen und Interaktionen mit dem Benutzer. Die Anforderungen werden in dieser Arbeit an die Benutzeroberfläche sowie an die Funktionalität der Beispielanwendung gestellt und sind aus den Evaluationskriterien der WebFrameworks aus Kapitel 5 abgeleitet.
Für die Beispielanwendung wird im Rahmen der funktionalen Anforderungen ein fachliches DomainModell erstellt. Es zeigt die Beziehungen zwischen den Objekten der Anwendung. Das Modell wird als Grundlage des späteren Datenbankentwurfs dienen.
Jede Beispielanwendung soll die Verwaltung und die Darstellung von Studenten sowie die dazugehörigen Studentenarbeiten ermöglichen. Ziel ist es nicht, eine vollständig in der Produktion einsetzbare Anwendung umzusetzen. Vielmehr soll gezeigt werden, ob sich bestimmte Anforderungen mit den entsprechenden WebFrameworks umsetzen lassen.
48
Abbildung 6.1: Klassenmodell der Beispielanwendung
n 1
Student + firtsname: String + lastname: String + matnr: Integer + faculty: String + address: String + email: String
Stwork + artofwork: String + title: String + startdate: Date + enddate: Date + defensedate: Date + note: Float
6 Entwurf und Implementierung
Die funktionalen Anforderungen an die Benutzeroberfläche und der WebAnwendung werden in Form von User Stories aufgelistet:
• Eine Benutzeroberfläche mit passendem Layout muss implementiert werden.• Studenten sowie Studentenarbeiten sollen verwaltet werden, das heißt angelegt, geän
dert und gelöscht.• Alle Angaben müssen vor dem Schreiben in die Datenbank validiert werden.• Jeder Student kann eine oder mehrere Studentenarbeiten besitzen, jede Studentenar
beit kann nur zu einem Studenten gehören.• Die Authentifizierung des Benutzers muss implementiert werden, das heißt die An
meldung eines Benutzers mit Überprüfung, ob er bereits angemeldet ist.• Den Benutzern müssen drei Benutzerrollen, Administrator, User und Gast, zugeord
net werden um die Rechte einzelner Benutzer einzuschränken.• Benutzer sollen nur von einem Administrator verwaltet werden.• Die Suchfunktion mit einer AjaxUnterstützung muss realisiert werden.• Eine FilterFunktion muss realisiert werden, die die Datensätze aufgabenspezifisch
aus der Datenbank auswählt und ausgibt.
Den Seitenablauf in der Beispielanwendung kann man sich in Form eines Ablaufdiagrammes vorstellen. Es stellt die Wege zwischen verschiedenen Views dar. Das Diagramm bietet einen Überblick über die WebAnwendung und das Zusammenwirken der einzelnen Views:
49
Abbildung 6.2: Skizze der Seitennavigation
6 Entwurf und Implementierung
Der Zugriff auf die Seiten der Beispielanwendung ist nur für die eingeloggten Benutzer erlaubt. Dabei werden drei Benutzergruppen definiert: Administrator, Redakteur und Gast. Je nach Benutzerprofil gibt es die Möglichkeit verschiedene Aktionen in der Webanwendung durchzuführen.
Nach der Anmeldung gelangt der Benutzer zur Startseite einer Beispielanwendung. Diese Seite stellt eine Liste aller vorhandenen Studenten mit den zugehörigen Studentenarbeiten dar. Je nach Benutzergruppe hat der Benutzer verschiedenste Aktionsmöglichkeiten. In der Studentenübersicht findet man – soweit man die erforderlichen Rechte hat, Verweise zu Aktionen wie Studenten hinzufügen, Studenten bearbeiten, Studentenarbeit hinzufügen, Studentenarbeit bearbeiten und Studentenarbeit löschen.
Die Detailansicht eines Studenten oder einer Studentenarbeit kann durch den Klick auf den Namen des Studenten oder den Titel der Studentenarbeit angezeigt werden. Beim Klicken wird man zu der Seite weitergeleitet, wo die Angaben zum Studenten oder zur Studentenarbeit genauer dargestellt werden. Über den Link Studenten hinzufügen bzw. Studentenarbeit hinzufügen gelangt man zur Seite, wo man einen neuen Studenten bzw. eine neue Studentenarbeit anlegen kann.
Für jeden Studenten können eine oder mehrere Studentenarbeiten angelegt werden. Jede Eingabe des Benutzers muss beim Schreiben in die Datenbank auf die Gültigkeit überprüft werden. Hiermit könnte zum Beispiel überprüft werden, ob es sich um eine Zahl oder einen String handelt. Oft ist es notwendig zu überprüfen, ob ein Wert in einem bestimmten Bereich liegt oder überhaupt vorhanden ist. Die Angaben zu einem Studenten oder zu einer Studentenarbeit können jederzeit geändert werden. Dafür ist der Link Bearbeiten vorgesehen.
Durch den Einbau von Filtern in die Beispielanwendung kann leicht überprüft werden, ob eine Manipulation an DatenbankEinträgen im WebFramework vorgenommen werden kann.
FilterFunktionen ermöglichen, die Datensätze aus der Datenbank spezifisch auszuwählen. Die Studentenarbeiten lassen sich nach verschiedenen Kriterien filtern. Dazu wird auf der rechten Seite der Startseite eine Liste von Filtern bereitgestellt, die in drei Gruppen geteilt wird: nach Verteidigung, nach Note und alle Einträge.
50
Abbildung 6.3: Filter
6 Entwurf und Implementierung
Das WebFramework muss nicht nur einen guten PluginSupport besitzen, sondern es muss auch einfach und flexibel genutzt werden können. Um dies zu überprüfen, werden in der Beispielanwendung zwei Plugins installiert: ein Plugin für die Seitennummerierung (Paginate) und ein AutorisierungsPlugin. Das PaginatePlugin ermöglicht seitenweise Ausgaben von Datensätzen aus der Datenbank. Diese Funktionalität wird in den meisten WebFrameworks als Plugin angeboten. Ein AutorisierungsPlugin ermöglicht den Zugriff auf die WebAnwendung nur für den angemeldeten Benutzer. Die Zugriffsrechte der Benutzergruppen zu den einzelnen Funktionalitäten sind in der folgenden Tabelle 5 dargestellt.
Funktionalität der Beispielanwendung (Aktion) Administrator Redakteur Gast
Studenten/Studentenarbeit auswählen (show) + + +
Studenten/Studentenarbeit bearbeiten (edit) + +
Studenten/Studentenarbeit löschen (delete) +
neuen Studenten/neue Studentenarbeit anlegen (new) + +
Benutzer auswählen (show) + +
Benutzer bearbeiten (edit) +
neuen Benutzer anlegen (new) +
+ zugelassen nicht zugelassen
Tabelle 5: Zugriffsrechte jeder Benutzerrolle
In jeder Beispielanwendung muss eine Suchfunktion eingebaut werden, die die Suche nach Studenten und entsprechenden Studentenarbeiten ermöglicht. Um zu überprüfen, wie das WebFramework mit Ajax arbeitet, wird die Suchfunktion mit AjaxUnterstützung realisiert. Dabei werden die Ergebnisse innerhalb der aktuellen Seite ausgegeben, ohne die Seite neu zu laden. Bei einem Suchergebnis handelt es sich nur um ein Teil der Ergebnisse. Die restlichen Ergebnisse sind durch „navigieren“ innerhalb des Suchergebnisses aufrufbar.
Im Anhang A Screenshots sind die Screenshots der Beispielanwendung beigefügt um einen Überblick über die Beschaffenheit und die Funktionalitäten zu erhalten.
51
Abbildung 6.4: AjaxSuchfunktion
6 Entwurf und Implementierung
6.2 Implementierung mit Ruby on Rails
Für die Implementierung der Beispielanwendung mit Rails wurde die Version 2.3.2. des Frameworks verwendet. Um die RailsAnwendung entwickeln zu können, werden folgende Komponenten gebraucht: Ruby in der neuesten Version, RubyGem, Rails, Datenbank (in diesem Fall MySQL), IDE NetBeans. Die genauen Installationsanweisungen sind im B.1 DieRuby on RailsInstallation zu finden.
6.2.1 Anwendungsrahmen und Verzeichnisstruktur
Die neue RailsAnwendung wird mit dem Befehl rails studentwork generiert. Nach diesem Befehl wird ein Projektverzeichnis studentwork mit einer ganzen Reihe von Unterverzeichnissen angelegt.
Die einzelnen Verzeichnisse haben folgende Bedeutung:• app/ Hauptverzeichnis für Modell, View, Controller und Helpersdatei• config/ enthält alle Konfigurationsdateien für die RailsAnwendung,
wie Datenbankkonfiguration, RailsUmgebungKonfiguration, Routing• db/ enthält das Datenbankschema und MigrationDateien• doc/ Ruby besitzt RubyDocSubFramework, das die Anwendungsdokumentation
automatisch erzeugen kann• lib/ hier werden anwendungsspezifische Bibliotheken abgelegt (z.B. von anderen
Herstellern)• log/ enthält alle Logfiles der Anwendung• public/ ist ein Wurzelverzeichnis eines Webservers und enthält die sich nicht verän
dernden Webdateien (JavaScriptDateien, Stylesheets, Grafiken)• script/ enthält standardmäßige Scripts, wie Codegeneratoren, Script zum Start des
Webservers (script)• test/ in diesem Verzeichnis liegen alle Tests: UnitTests, Integrationstests• tmp/ enthält temporäre Dateien, die während der Verarbeitung zwischengespeichert
werden (z.B. Session und CacheDateien etc.)• vendor/ hier werden Plugins und externe Bibliotheken abgelegt
Die Anwendung kann sofort ausgeführt werden, indem man den Webserver aus dem Projektverzeichnis mit dem Befehl ruby script/server webrick startet.
52
6 Entwurf und Implementierung
6.2.2 Modelle anlegen
Bevor man mit der Entwicklung beginnt, müssen noch die Datenbanken angelegt werden. Es werden drei verschiedene Datenbanken für die Umgebungen development (Entwicklung), test(Test) und production (Produktion) erstellt.
Die DatenbankKonfiguration wird in die Datei config/database.yml gespeichert und kann jederzeit angepasst werden. Nachdem eine leere Datenbank erzeugt wurde, kann man die Modelle anlegen. Als Grundlage für das Datenbankschema wird das DomainModell aus Abbildung 6.1 verwendet.
Für das Beispielprojekt werden zwei Modelle Student und Stwork mit Hilfe des GeneratorScripts script/generate generiert.
Es werden zwei leere Modellklassen student.rb und stwork.rb und zwei Migrationsdateien20090613102908_create_students.rb und 20090613103051_create_stworks.rb erstellt. Die Tabellen müssen noch in der Migrationsdatei um die einzelnen Spalten erweitert werden (Quellcode 12).
Die Beziehung zwischen den Tabellen wird im Modell explizit beschrieben. Die beiden Modelle Students und Stworks stehen in einer 1:nBeziehung zueinander: eine Studentenarbeit gehört immer zu genau einem Studenten. Die Tabelle Stworks referenziert über den Fremdschlüssel student_id die Tabelle Students. Der Name der Fremdschlüsselspalte muss aus dem referenzierten Tabellennamen im Singular mit dem Zusatz _id bestehen.
53
Abbildung 6.5: config/database.yml
Quellcode 12: Erstellung des StworkDomainModells
1 class CreateStworks < ActiveRecord::Migration 2 def self.up 3 create_table :stworks do |t| 4 t.string :artofwork 5 t.string :title 6 t.datetime :startdate 7 t.datetime :enddate 8 t.datetime :defensedate 9 t.float :note 10 t.integer :student_id 11 end 12 end 13 ...
6 Entwurf und Implementierung
Um die 1:nBeziehung auf der Modellebene zu deklarieren werden in die Modelldeklaration Befehle has_many und belongs_to hinzugefügt.
Die Validierung im Projekt findet auf zwei Arten statt: durch die Nutzung von Klassenmethoden und durch Überschreiben der validateMethode. Die validateMethode überprüft die Attribute eines Modells auf Gültigkeit. Die Methode wird als protected definiert und kann überschrieben werden. Die Validierung der Klassenmethoden wird für die immer wiederholenden Prüfungen durchgeführt. Diese Methode wird in der Deklaration von Modellklassen verwendet, so dass die Modelle um das gewünschte Validierungsverhalten erweitert werden. Zum Beispiel findet die Validierung durch Klassenmethoden folgendermaßen statt:
Die validateMethode beschreibt zum Beispiel das Verhalten des matnrAttributs:
6.2.3 Implementierung des User Interfaces
Die Controller und die Views werden für die Beispielanwendung mit Hilfe des ScaffoldGenerators erstellt:
Nach diesen Befehlen werden automatisch zwei Controller, students_controller.rb und stworks_controller.rb erstellt.
54
$ ruby script/generate scaffold student student $ ruby script/generate scaffold stwork stwork
Quellcode 14: Validierung durch Klassenmethoden
1 class Student < ActiveRecord::Base 2 validates_presence_of :firstname, :lastname, 3 :message => "darf nicht leer sein" 4 validates_format_of :email, 5 :with => /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i, 6 :message => "ist unkorrekt" 7 end
Quellcode 15: validateMethode der Klasse Student
1 protected 2 def validate 3 errors.add(:matnr,"muss größer als 0 sein") unless matnr.nil? || matnr >0 4 end
Quellcode 13: 1:nBeziehung zwischen den Modellen Students und Stworks
1 class Stwork < ActiveRecord::Base 2 belongs_to :student 3 ... 4 class Student < ActiveRecord::Base 5 has_many :stworks, :dependent => :destroy 6 ...
6 Entwurf und Implementierung
Jeder Controller enthält so genannte Aktionen. Für jede Aktion außer destroy wurde auch automatisch jeweils ein View angelegt. Die angelegten Aktionen haben folgende Bedeutung:
• index Auflisten von allen Einträgen• show einen bestimmten Datensatz anzeigen• new neuen Datensatz anlegen• edit den Datensatz editieren• create neues Objekt in der Datenbank speichern• update den Datensatz aktualisieren• destroy den Datensatz löschen
Die Grundstruktur der Webseiten wird an zentraler Stelle, in einer separaten LayoutDatei mainlayout.rhtml abgelegt (Quellcode 16). Über stylesheet_link_tag werden die CSSDateien scaffold.css und student.css eingebunden, die sich im stylesheetsVerzeichnis befinden.
Über javascript_include_tag wird eine StandardJavaScriptDatei eingebunden. Diese wird dann bei der AjaxSuche notwendig. In dem divContainer menu wird später die Navigation der WebAnwendung eingebunden. Die eigentliche Anwendung wird im mainBereich eingebunden. Dies wird so realisiert, dass anstelle des content_for_layout von Rails automatisch die jeweiligen Templates eingebunden werden. Für den FußBereich wird _footer.htmlPartial benutzt. Dadurch besitzt die WebAnwendung einheitliche Kopf sowie Fußbereiche und nur der Inhalt jeder Webseite wird dynamisch geändert. Die Struktur von jeden View ist in zwei Spalten geteilt. In der linken Spalte sind die Inhalte jeder Webseite sowie die paginateFunktion, in der rechten Spalte sind die Funktionalitäten der WebAnwendung angeordnet. Die LayoutDatei wird um die Navigation erweitert, die im menuBereich platziert und für alle Views der Webanwendung gleich ist.
55
Quellcode 17: Navigation der Beispielanwendung
1 <body> 2 <div class="banner"> 3 <div class="menu"> 4 <%= link_to 'Startseite',:controller =>'students',:action =>'index'%> 5 <%= link_to 'Benutzerliste',:controller =>'users',:action =>'index'%> 6 <%= link_to 'Neue Benutzer',:controller =>'users',:action =>'new'%> 7 </div> 8 ... 9 </body>
Quellcode 16: mainlayout.rhtmlDatei
1 <html> 2 <head> 3 <title>Verwaltung von Studentenarbeiten</title> 4 <%= stylesheet_link_tag "scaffold","student",:media =>"all" %> 5 <%= javascript_include_tag :defaults %> 6 </head> 7 <body> 8 <div class="banner"> 9 <div class="menu"> 10 <%= link_to 'Startseite',:controller =>'students',:action =>'index'%> 11 <%= link_to 'Benutzerliste',:controller =>'users',:action =>'index'%> 12 <%= link_to 'Neue Benutzer',:controller =>'users',:action =>'new'%> 13 </div> 14 </div> 15 <div class="main"><%= @content_for_layout %></div> 16 <div class="footer"><%= render :partial => 'footer' %></div> 17 </body> 18 </html>
6 Entwurf und Implementierung
Damit die LayoutDatei main_layout.rhtml für alle Views der WebAnwendung wirksam wird, muss sie in den dazugehörigen Controllern explizit deklariert werden:
Es kann vorkommen, dass viele Datensätze ausgegeben werden müssen. Dann ist es sinnvoll, die Ergebnisse seitenweise auszugeben. Ab Rails Version 2.0 wird diese Funktion nicht mehr automatisch integriert und muss als Plugin installiert werden. Es gibt eine große Auswahl von solchen Plugins. In dem Projekt wurde für will_paginate entschieden, da es einfach zu installieren und zu benutzen ist. Das Plugin wird aus dem Projektverzeichnis mit folgendem Befehl installiert:
Nach der erfolgreichen Installation erscheint das Plugin im Verzeichnis vendor/plugin. Die Vorgehensweise bei der Nutzung von Plugins ist folgende: zuerst werden die im Controller definierten und ausschließlich im View benutzt. In dem Controller werden die Parameter für die seitenweise Ausgabe der Beiträge definiert:
Bei den gefundenen Datensätzen wird die paginateMethode mit folgendem Parameter angewendet: der pageParameter teilt dem Plugin die aktuell anzuzeigende Seite mit, der per_pageParameter definiert, wie viele Ergebnisse pro Seite ausgegeben werden sollen. Um die Ergebnisse der Pagination, zum Beispiel die Liste von Studenten, in einem View anzuzeigen, wird der Befehl <%= will_paginate @students %> benutzt.
Die Filter werden in einem student/index.htmlView als einfache Links realisiert:
56
layout 'main_layout'
$ ruby script/plugin install svn://errtheblog.com/svn/plugins/will_paginate
Quellcode 18: Paginate Plugin
1 class StudentsController < ApplicationController 2 def index 3 @students = Student.find(:all,:order =>sort_order('created_at')).paginate 4 :page => params[:page], 5 :per_page => 6 6 end 7 ... 8 end
Quellcode 19: Definition der Filter in einem index.htmlView
1 <span class="filter">Nach Verteidigung:</span> 2 <%= link_to "Innerhalb einer Woche",:controller => :stworks, 3 :action => :index, :id =>'woche'%> 4 <%= link_to "Innerhalb eines Monats", :controller => :stworks, 5 :action => :index, :id =>'monat'%> 6 ...
6 Entwurf und Implementierung
Jeder Filtereintrag erhält einen eigenen idParameter, durch den man im Controller erkennen kann welcher Link geklickt wurde. Im stworks_controller.rb wird dieser idParameter in die Variable @status gespeichert. Ausgehend, welcher Wert übergeben wird, wird die entsprechende Suchanfrage mit Hilfe der findMethode durchgeführt.
Im obigen Beispiel werden alle Datensätze gefunden, bei denen die Verteidigung innerhalb einer Woche stattfinden soll. Mit der paginateMethode werden die gefundenen Datensätze zu je fünf Einträge pro Seite ausgegeben. Wenn kein params[id]Parameter dem Controller übergeben wird, wird die gesamte Liste von Datensätzen aus der Datenbank ausgegeben.
6.2.4 Suchfunktion mit Ajax
Die Verwendung von Ajax innerhalb von Rails ist sehr einfach. Als erstes muss eine AjaxAktion ausgelöst werden. Dies kann ein Klick auf einer Schaltfläche, einem Link oder eine vom Benutzer vorgenommene Änderung in einem Formular bzw. einem Feld sein. Ist das Ereignis eingetroffen, werden mit der AjaxAktion verbundene Daten mittels XMLHttpRequest asynchron an den Server geschickt. Auf dem Server werden mit dem Request die in der Aktion stehenden Operationen durchgeführt und ein HTMLFragment wird als Response zurückgeliefert. Dieses HTMLFragment wird auf der ClientSeite mit Hilfe von JavaScriptCode empfangen und benutzt, um an einer definierten Stelle, meist innerhalb eines bestimmten divBlocks, den Inhalt zu aktualisieren. Um mit der AjaxImplementierung beginnen zu können, muss als Erstes die JavaScriptBibliothek namens Prototype ins Layout eingebunden werden. Die PrototypeBibliothek wird über den javascript_include_tagBefehl in die LayoutDatei main_layout.rhtml integriert:
Der defaultsParameter sagt, dass außer prototype.js alle Dateien (application.js, control.js, dragdrop.js und effects.js) geladen werden müssen. Alle diese Dateien werden bereits bei der Erstellung der WebAnwendung automatisch im Verzeichnis javascripts generiert.
57
<%= javascript_include_tag :defaults %>
Quellcode 20: Definition der Filter in einem stworks_controller.rb
1 def index 3 @status = params[:id] 4 #Nach Verteidigung 5 if @status == 'woche' 6 @stworks=Stwork.find(:all, :conditions => ["defensedate >= ? and 7 defensedate < ?", Date.today(),Date.today()+7 ]).paginate 8 :page => params[:page], :per_page => 5 9 ... 10 end
6 Entwurf und Implementierung
Als Nächstes wird ein Ajaxbasiertes Formular erstellt, das auf der Startseite erscheinen soll und eine EchtzeitSuche ermöglicht. Die aktualisierten Ergebnisse werden innerhalb der aktuellen Seite, noch während der Benutzer seine Suchbegriffe eingibt, ausgegeben:
Das Formular hat ein normales Textfeld mit den Namen search, in das der Suchbegriff eingetragen wird. Dieses Textfeld wird mit Hilfe von einem Observer observe_field auf Änderungen beobachtet, um die Änderungen, wenn solche eintreten, an den Server zu melden. Der Observer verlangt nach der id des überwachten Elements – in unserem Fall also search_form.
Das :frequencyAttribut legt fest, wie oft das Feld auf Änderungen überprüft wird. Unter dem :updateAttribut steht das DOMElement, das aktualisiert werden muss, in unserem Fall ist es ein divContainer namens results. Die Option :url definiert die Aktion, die aufgerufen werden muss, wenn der Inhalt des Feldes geändert wird. Das letzte Element :with spezifiziert die Parameter für den XMLHttpRequest. Standardmäßig wird der Wert des beobachteten Feldes übermittelt. In dem stworks_controller.rb wird eine neue searchAktion definiert, die eine Anfrage bearbeitet und nach Übereinstimmungen sucht:
Die Aktion überprüft als Erstes ob der Request ein AjaxAufruf ist. Wenn ja, wird die eigentliche Suche mit Hilfe der findMethode der StworkKlasse durchgeführt. Es wird die eingegebene Suchanfrage als params[search_text]Hash übergeben. Der conditionsParameter erzeugt eine Reihe von SQLLIKEKlauseln, die dann miteinander verknüpft werden. Dabei wird nach dem Titel als auch nach der Art der Studentenarbeit gesucht. Die Liste der Suchergebnisse wird anschließend an ein _search.htmlPartial übergeben, wo diese dann dargestellt werden.
58
Quellcode 21: Ajaxbasiertes Formular in der Datei app/views/stworks/index.rhtml
1 <div id="search"> 2 Studentenarbeit suchen:<input type="text" id="search_form" name="search"/> 3 <div id="results"></div> 4 <%= observe_field 'search_form', :frequency => 0.5, :update => 'results', 5 :url => { :controller =>'stworks', :action=>'search' }, 6 :with => "'search_text=' + escape(value)" %> 7 </div>
Quellcode 22: searchMethode
1 def search 2 if request.xhr? 3 @stworks=Stwork.find(:all,:conditions =>["title like ? or artofwork like ?", 4 "%#{params[:search_text]}%", 5 "%#{params[:search_text]}%"]) 6 render :partial => "search" 7 else 8 render :text => "No results found", :layout => false 9 end 10 end
6 Entwurf und Implementierung
6.2.5 RailsAuthentifizierung
Jede Applikation benötigt einen passwortgeschützten Bereich, der mehrere BenutzerAuthentifizierungen ermöglicht. Eine der populärsten Erweiterungen für die Authentifizierung in Rails ist das auf “acts as authenticated” basierende Restful Authentication Plugin.1 Es erstellt einen AuthenticationCode für das Projekt und bietet viele Vorteile: eine Registrierung mit oder ohne Aktivierung, An und Abmeldung. Bevor man aber mit der Installation beginnt, muss man prüfen, dass die Rails Version 2.0 installiert ist und in dem Projekt keine Tabelle users existiert, da das Plugin seine eigene Tabelle users erstellt. Um das Plugin zu installieren, gibt man folgenden Befehl ein:
Das Plugin erstellt zwei neue Controller: user_controller und session_controller. Der UserController übernimmt die Registrierung von Benutzern, der SessionController ist verantwortlich für die An und Abmeldung. Die beiden Controller werden wie folgt generiert:
Zusätzlich werden das Modell user.rb und die dazugehörigen Views mit generiert. Als nächstes müssen die nötigen Tabellen für den Benutzer erstellt werden. Dafür reicht es einfach die Migration rake db:migrate durchzuführen. Eigentlich hat der PluginGenerator die routes.rbDatei schon bei der Erzeugung von zwei neuen Controller angepasst und die entsprechenden Einträge für den User und SessionController eingefügt. Anschließend wird in jeden Controller, zu dem der Zugriff eingeschränkt werden muss, folgende Zeile eingefügt:
Durch diesen Befehl wird der Zugriff zu allen Views, zu denen in diesem Controller eine Aktion existiert, verweigert. Wenn der nicht angemeldete Benutzer die entsprechende Seite aufruft, wird er automatisch auf die LoginSeite weitergeleitet:
1 http://agilewebdevelopment.com/plugins/restful_authentication
59
$ script/plugin source http://svn.techno-weenie.net/projects/plugins $ script/plugin install restful_authentication
$ ruby script/generate authenticated user sessions
$ before_filter :login_required
Quellcode 23: config/routes.rb
1 ActionController::Routing::Routes.draw do |map| 2 map.register '/register', :controller => 'users', :action => 'create' 3 map.signup '/signup', :controller => 'users', :action => 'new' 4 map.resources :users 5 map.resource :session
6 Entwurf und Implementierung
6.3 Realisierung mit Django
Die Django Installation kann je nach LinuxDistribution beliebig einfach oder kompliziert sein. Zur Entwicklung unter Django werden folgende Elemente benötigt: Python 2.3 oder höher, Subversion Client, eine relationale Datenbank und Django 1.1.0 selbst. Die Installationsanweisungen sind im B.2 Die DjangoInstallation zu finden.
6.3.1 Anwendungsrahmen und Verzeichnisstruktur
Um ein neues Projekt anzulegen, wird im Terminal folgender Befehl eingegeben:
Django generiert daraufhin ein Verzeichnis studentworkdj mit den folgenden Dateien:• __init__.py ist notwendig, damit das Projekt als PythonModul importierbar ist• manage.py ist ein Script zur Verwaltung des Projekts• settings.py speichert alle Einstellungen und Konfigurationen des Projekts• urls.py legt die Konfiguration der URLs fest
Ein DjangoProjekt wird in verschiedene Applikationen aufgeteilt. Jedes Projekt kann mehrere Applikationen enthalten, jede Applikation ist dabei eine WebApplikation, die eine bestimmte Aufgabe erfüllt und wird wie folgt erstellt:
Django hat einen eingebauten Entwicklungsserver, der automatisch die Änderungen am Code überwacht und lädt, ohne Neustart des Servers. Der Server muss im Projektverzeichnis gestartet werden:
Dieser Server soll nur als Entwicklungsserver und nicht als Produktionsserver benutzt werden. In der Produktion muss ein Server wie z.B. Apache oder Lighttpd benutzt werden.
Um mit dem Projekt arbeiten zu können, müssen bestimmte Einstellungen in der settings.pyDatei vorgenommen werden. Nähere Informationen sind der Anweisungen C.1.1 Einstellungen des DjangoProjektes zu entnehmen.
60
$ django-admin.py startproject studentworkdj
$ django-admin.py startapp students
$ python manage.py runserver
6 Entwurf und Implementierung
6.3.2 Modelle anlegen
Da das Projekt zwei Tabellen student und studentwork benötigt, werden in der Datei models.py zwei Modellklassen angelegt. Die Klasse Student enthält die Angaben zum Studenten wie Vor, Nachname, Matrikelnummer, Studiengang u.s.w.:
Die Klasse Studentwork enthält die Angaben zur Studentenarbeit wie Art der Arbeit, Titel, Start, End, Verteidigungsdatum und Note. Die Klasse besitzt eine Besonderheit: das Feld artofwork ist als Typ STWORKS_CHOICES definiert und akzeptiert eine bestimmte Anzahl von Eingaben. Die entsprechende Definition der Studentenarbeiten muss vorher erfolgen:
Für jedes Datenfeld wird ein Name und ein Datentyp deklariert. Die Datentypen und dazu eingegebenen Parameter werden von Django zur Validierung von Objekten beim Schreiben in die Datenbank verwendet. Parameter blank=True gibt an, ob das Feld optional ist und leer sein darf. Standardmäßig sind alle Felder als Pflichtfelder definiert. Sehr wichtig ist auch, dass jede Klasse die Methode __unicode__ überschreibt und eine Klartextvariante ausgibt. Dieser Eintag kann in einem Auswahlfeld angezeigt werden. Es wird z.B. beim Anlegen einer Studentenarbeit im AdminInterface eine Liste von Studenten zur Auswahl zur Verfügung gestellt. Für die Klasse Student wird beispielsweise Vor und Nachname ausgegeben:
61
Quellcode 25: Modellklasse Studentwork
1 STWORKS_CHOICES = ( 2 ('Abschlussarbeit','Abschlussarbeit'),('Bachelorarbeit','Bachelorarbeit'), 3 ('Diplomarbeit','Diplomarbeit'),('Doktorarbeit','Doktorarbeit'), 4 ('Masterarbeit','Masterarbeit'),('Projektarbeit','Projektarbeit'), 5 ('Seminararbeit','Seminararbeit'),('Studienarbeit','Studienarbeit'), 6 ) 7 class Studentwork(models.Model): 8 artofwork = models.CharField(max_length=30, choices=STWORKS_CHOICES, 9 title = models.CharField(max_length=50) 10 start_date = models.DateField() 11 end_date = models.DateField() 12 defend_date = models.DateField(blank=True, null=True) 13 note = models.FloatField(verbose_name='note', blank=True, null=True) 14 student = models.ForeignKey(Student)
def __unicode__ (self): return u'%s %s' %(self.last_name, self.first_name)
Quellcode 24: Modellklasse Student
1 from django.db import models 2 class Student(models.Model): 3 first_name = models.CharField(max_length=30) 4 last_name = models.CharField(max_length=30) 5 matnr = models.IntegerField() 6 facultet = models.CharField(max_length=30) 7 address = models.CharField(max_length=60) 8 email = models.EmailField(max_length=30)
6 Entwurf und Implementierung
6.3.3 Anwendung der Administrationsoberfläche
Um die benutzerdefinierten Modelle zur Administrationsoberfläche hinzufügen, muss in dem Applikationsordner eine admin.pyDatei erstellt werden. Dieser Datei müssen alle benötigten Modellklassen hinzugefügt werden:
Über die Administrationsoberfläche kann man Studenten und Studentenarbeiten editieren, neue hinzufügen und löschen. Für die Anzeige der Studenten nutzt Django die __unicode__Methode, die oben in der models.py Datei schon definiert wurde. In der admin.pyDatei kann man für jede Modellklasse mit Hilfe der ModelAdminKlasse festlegen, welche Optionen das AdminInterface anzeigen soll:
• list_display definiert Felder, die in der Übersichtsliste angezeigt werden.• search_fields integriert eine Suchmaske in die Übersichtsliste. Die Feldnamen geben
an, welche Felder Django durchsuchen soll.• list_filter zeigt einen Filter an, der die Ergebnisse nach der Auswahl der unterschied
lichen Feldeinträge sortiert.
Anschließend werden die neu definierten ModelAdminKlassen StudentAdmin und StudentworkAdmin dem AdminInterface hinzugefügt und der Student bzw. StudentworkKlasse zugeordnet:
Das AdminInterface muss noch dem ProjektLayout angepasst werden. Standardmäßig sind die TemplateDateien des AdminInterfaces unter folgender Adresse zu finden:
62
admin.site.register(Student, StudentAdmin) admin.site.register(Studentwork, StudentworkAdmin)
/home/helga/web/django_src/django/contrib/admin/templates/admin
Quellcode 26: admin.pyDatei der studentsApplikation
1 from django.contrib import admin 2 from studentworkdj.students.models import Student, Studentwork 3 4 admin.site.register(Student) 5 admin.site.register(Studentwork)
Quellcode 27: Optionen des AdminInterfaces
1 class StudentworkAdmin(admin.ModelAdmin): 2 3 list_display = ('title','artofwork','start_date','end_date','defend_date') 4 list_filter = ('defend_date','end_date','note',) 5 search_fields = ('title', 'artofwork',)
6 Entwurf und Implementierung
Um für das AdminInterface ein eigenes Layout zu verwenden, muss dem Verzeichnis templates des Projektverzeichnisses ein Unterverzeichnis admin hinzugefügt werden und die Dateien aus dem oben genannten Ordner dorthin kopiert werden. Diese Templates können jetzt beliebig an das ProjektLayout angepasst werden. Die Änderungen werden nur in dem AdminInterface des aktuellen Beispielprojektes wirksam.
6.3.4 Implementierung des User Interfaces
Das Beispielprojekt hat drei ViewFunktionen: eine zum Anzeigen der Studentenliste index (Quellcode 28) eine für die Ansicht eines einzelnen Studenten readStudent und eine für die Ansicht einer einzelnen Studentenarbeit readStwork.
Es ist sinnvoll diese Dateien in einem eigenen Verzeichnis templates innerhalb des Applikationsverzeichnisses students abzulegen. Per import werden am Anfang die benutzten Klassen eingebunden, beide Modellklassen Student und Studentwork aus der Applikation students, die RequestContextKlasse aus dem Modul django.template und die Klasse render_to_response aus dem Modul django.shortcuts, die man in einem View nutzt um die Ergebnisse ins Template zurückzugeben. Die ViewFunktion bekommt von Django immer einen Parameter namens request übergeben, mit dem man auf bestimmte Informationen der Abfrage zugreifen kann.
Innerhalb von index wird eine Liste namens student_list verwaltet, die alle Studenten aus dem Datenmodell Student speichert und dann an das Template students/templates/index.html weiterleitet. Der Funktion render_to_response werden drei Argumente übergeben: der Name des Templates, eine Studentenliste und ein Kontext. Jetzt muss noch das zugehörige Template index.html im Ordner /students/templates erstellt werden. In dem index.html wurden zwei Links eingefügt um die Detailübersicht für einen einzelnen Studenten oder eine einzelne Studentenarbeit anzuzeigen:
63
<a href="student/{{student.id}}/">{{student.last_name}}{{student.first_name}}</a> <a href="studentwork/{{stwork.id}}">{{stwork.title}}</a>
Quellcode 28: indexView
1 from studentworkdj.students.models import Student, Studentwork 2 from django.template.context import RequestContext 3 from django.shortcuts import render_to_response, get_object_or_404 4 5 def index( request ): 6 student_list = Student.objects.all() 7 return render_to_response('index.html',{'student_list': student_list}, 8 context_instance=RequestContext(request))
6 Entwurf und Implementierung
Es fehlen noch die beiden Funktionen readStudent (Quellcode 29) und readStwork, die in der view.pyDatei folgendermaßen definiert werden:
Diese beiden Funktionen benötigen auch die dazugehörige TemplateDatei. Als Beispiel kann das readStudent.htmlTemplate dienen:
Anschließend werden beide Funktionen in die URLKonfiguration students/urls.py übernommen (Quellcode 31). Dabei ist zu beachten, dass die id des Studenten und id der Studentenarbeit in der URL mit übergeben werden müssen. Der in den Klammern stehende Teil des regulären Ausdrucks wird beim Vergleich in eine Variable gespeichert. An den damit verknüpften View werden diese Variablen als Argument übergeben.
Die Seitennummerierung wird in Django als Plugin realisiert. Die PaginationAnwendung wird in die settings.pyDatei in dem INSTALLED_APPSBereich hinzugefügt:
Unter dem MIDDLEWARE_CLASSESBereich wird eine weitere Zeile hinzugefügt:
Wenn die folgenden Einstellungen noch nicht in der settings.pyDatei enthalten sind, muss der TEMPLATE_CONTEXT_PROCESSORSEintrag hinzugefügt werden.
64
Quellcode 30: readStudent.htmlTemplate
1 {% extends "base.html" %} 2 ... 3 {{student.first_name}} {{student.last_name}} 4 ... 5 {% for stwork in stworks %} 6 {{stwork.artofwork}} 7 <a href="studentwork/{{stwork.id}}/">{{ stwork.title }}</a> 6 {% endfor %}
'pagination',
'pagination.middleware.PaginationMiddleware',
Quellcode 31: URL Definition
1 urlpatterns = patterns('', 2 url(r'^student/(?P<student_id>\d+)/$', readStudent), 3 url(r'^studentwork/(?P<stwork_id>\d+)/$', readStwork), 4 ... 5 )
Quellcode 29: readStudentFunktionen
1 def readStudent(request, student_id): 2 student = get_object_or_404(Student, pk=student_id) 3 return render_to_response('readStudent.html', 4 {'stworks': student.studentwork_set.all(),'student': student}, 5 context_instance = RequestContext( request ))
6 Entwurf und Implementierung
Um die PaginateTags zu laden, wird der Befehl {% load pagination_tags %}benutzt. Die Aufteilung und Ausgabe erfolgt mit dem autopaginateBefehl.
Die Liste von Einträgen, die seitenweise geteilt werden müssen, z.B. die Studentenliste, ist in der Variable student_list gespeichert. Der zweite Wert gibt an, wie viele Einträge pro Seite benutzt werden müssen. Um jede aktuelle Seite anzuzeigen, wird der Befehl {% paginate %} benutzt.
Da Django bereits ein umfangreiches AdminInterface hat, ist es unnötig, weitere AuthentifizierungPlugins zu installieren. Es darf nur den Zugriff auf die studentsApplikation für die registrierten Benutzer gestatten. Dies wird dadurch erreicht, dass in allen ViewFunktionen der studentsApplikation eine Anfrage durchgeführt wird:
Die Funktion request.user.is_authenticated überprüft, ob ein Benutzer angemeldet ist, wenn nicht, wird der Nutzer zur Login Seite weitergeleitet.
6.3.5 Suchfunktion mit Ajax
Die Suchfunktion wird mit Hilfe des JavaScriptFrameworks jQuery2 entwickelt. Die letzte Version des Frameworks kann von der offiziellen Webseite geladen werden. Am besten geeignet ist eine unkomprimierte Version der Datei.
Die geladene jquery.jsDatei wird als Erstes ins Projektverzeichnis in den media/jsOrdner kopiert und dann in die Datei base.html importiert. Danach steht das Framework zur Verfügung:
2 http://docs.jquery.com/Downloading_jQuery
65
<script type="text/javascript" src="{{ MEDIA_URL }}js/jquery.js"></script>
{% autopaginate student_list 4 %}
Quellcode 32: Zugriffsbeschränkung
1 def index( request ): 2 if request.user.is_authenticated(): 3 ... 4 else: 5 return HttpResponseRedirect('/admin')
6 Entwurf und Implementierung
Die clientseitige Bearbeitung wird folgendermaßen realisiert. In der Datei students/templates/index.html wird als Erstes das Suchformular eingebaut, das ein einfaches Suchfeld mit Buttons und ein divElement namens searchResults enthält. Sobald die Suchergebnisse des Servers vorhanden sind, werden sie in den divElement angezeigt:
Das Framework jQuery wird dazu benutzt um auf die Elemente des DOMModells zugreifen zu können. Es wird eine jQueryFunktion in students/templates/index.html implementiert:
Als Erstes wird das Dokument mit der readyFunktion überprüft und auf eine Benutzeraktion gewartet. Nach dem Laden des DOM wird gewartet, bis die entsprechenden Events ausgeführt werden, in dem Fall wird ein Button nach seiner id ausgewählt. Wenn der searchSubmitButton angeklickt wird, wird das Element aus dem globalen jQueryObjekt ausgewählt. Die clickFunktion fügt dem ausgewählten Objekt, in unserem Fall dem Button, ein KlickEvent hinzu und führt die Funktion aus. Durch die valFunktion wird aus der qVariablen das erste passende Element des Eingangwertes bewertet, geladen und an die searchMethode übergeben. Als Nächstes wird die URLKonfiguration ergänzt:
Die searchFunktion übernimmt die serverseitige Bearbeitung (Quellcode 35). Um komplexe Abfragen mit ODER und UNDAnweisungen durchzuführen wird ein QObjekt benötigt, das aus dem django.db.modelsModul importiert wird. Ein QObjekt ist ein Objekt, das eine Liste von SchlüsselArgumenten zusammenfasst. In diesem Fall heißt die Liste qset. Die einzelnen Argumente werden mit der ODERAnweisung verkettet. Als Suchfelder werden die Felder first_name und last_name aus dem StudentDatenmodell und title und artofwork aus dem StudentworkDatenmodell benutzt.
66
urlpatterns = patterns('', url( r'^search/$', search, name = 'student_search' ), ...
Quellcode 33: Suchformular in der students/templates/index.htmlDatei
1 <div id="search_box"> 2 <input id="q" type="text" class="search_input"/> 3 <input id="searchSubmit" type="submit" value="Suchen"/><br/> 4 <div id="searchResults"></div> 5 </div>
Quellcode 34: JavaScriptFunktion mit jQuery
1 <script type="text/javascript"> 2 $(document).ready( function() { 3 $('#searchSubmit' ).click( function() { 4 q = $( '#q' ).val(); 5 $('#searchResults').load('{% url student_search %}?q='+q); 7 }); 8 }); 9 </script>
6 Entwurf und Implementierung
Durch die distinctMethode können die doppelten Zeilen aus den Abfrage Ergebnissen entfernt werden. Geht die Abfrage über mehrere Tabellen, kann es passieren, dass einige Ergebnisse doppelt vorkommen. Mehr ist in der DjangoDokumentation nachzulesen.3 Die is_ajax Funktion liefert true, wenn der Auftrag über ein XMLHttpRequest geliefert wurde.4 Die gefundenen Ergebnisse werden an das Template searchResults.html weitergeleitet und dargestellt.
6.4 Realisierung mit Grails
Für die Implementierung des Prototypen mit Grails wurde die Version 1.1 verwendet. Voraussetzung für die Installation von Grails ist die JDKInstallation. Die genauen Informationen zur Installation sind unter B.3 Die GrailsInstallation zu finden.
6.4.1 Anwendungsrahmen und Verzeichnisstruktur
Eine neue GrailsAnwendung wird mit dem Befehl grails createapp, gefolgt von dem Namen der neuen Grails Applikation, erstellt:
3 http://docs.djangoproject.com/en/dev/ref/models/querysets/4 http://docs.djangoproject.com/en/dev/ref/requestresponse/
67
$ grails create-app studentworkgr
Quellcode 35: searchFunktion
1 from django.db.models import Q 2 3 def search(request): 4 if request.is_ajax(): 5 query = request.GET.get('q', '') 6 if query: 7 qset = ( 8 Q(first_name__icontains=query) | Q(last_name__icontains=query) | 9 Q(studentwork__title__icontains=query) | 10 Q(studentwork__artofwork__icontains=query) 11 ) 12 results = Student.objects.filter(qset).distinct() 13 else: 14 results = [] 15 return render_to_response('searchResults.html', 16 {'results':results,'query':query,},context_instance=RequestContext(request))
6 Entwurf und Implementierung
Grails erzeugt daraufhin ein entsprechendes GrailsApplikationProjektverzeichnis, das folgende Verzeichnisstruktur hat:
• grailsapp/conf Konfigurationsdateien• grailsapp/controllers Controllers• grailsapp/domain DomainModelle • grailsapp/i18n Nachrichten, vordefinierte Fehlermeldungen• grailsapp/services Services• grailsapp/taglib TagLibraries• grailsapp/utils Utilites• grailsapp/views Views• lib/ .jarJavaArchive• scr/ Java und GroovyQuellcode• test/ Unit und IntegrationsTests der Webanwendung • webapp Zusätzliche Webdaten (JavaScript, CSS)
Die so erzeugte WebAnwendung ist bereits ohne weitere Konfigurationen funktionsfähig und kann aus dem Projektverzeichnis mit dem grails runappBefehl gestartet werden. Ein ServletContainer wie Tomcat, muss dabei nicht installiert werden, da Grails bereits mit dem eingebauten JettyWebserver ausgeliefert wird.
Nach diesem Befehl kompiliert und startet Grails die Webanwendung mit Hilfe von Jetty. Die Webapplikation läuft standardmäßig auf dem Port 8080 und ist unter Adresse: http://localhost/studentworkgr abrufbar. GrailsAnwendungen können im laufenden Betrieb weiterentwickelt werden. Das Kompilieren und Neustarten des Webservers nach jeder Änderung ist nicht notwendig.
Grails liefert standardmäßig HSQL5 als InMemoryDatenbank mit, bei der die Daten nicht auf dem Server gesichert werden müssen. Für die neue Webapplikation bedeutet dies, dass man sich am Anfang nicht um die Datenbank kümmern muss und direkt am DomainModell der Applikation arbeiten kann. Aber diese Daten stehen nach jedem Serverneustart nicht mehr zur Verfügung. Grails ermöglicht die Einbindung von externen Objektrelationalen Datenbanken. Deren Verwendung ist aber nicht zwingend notwendig, da für jede neue Webanwendung standardmäßig eine HSQLDatenbank erzeugt wird.
Nähere Erläuterungen sind im Anhang C Einstellungen des Projektes zu finden.
5 http://de.wikipedia.org/wiki/HSQLDB
68
6 Entwurf und Implementierung
6.4.2 DomainModelle
Der wichtigste Teil einer WebAanwendung sind ihre DomainModelle. In der Beispielanwendung werden zwei DomainModelle Student und Stwork angelegt:
Im Ordner grailsapp/domain werden zwei leere GroovyKlassen Student.groovy und Stwork.groovy und zusätzlich die zugehörigen UnitTests in den entsprechenden Verzeichnissen angelegt. Als Nächstes werden die DomainKlassen um die folgenden Felder erweitert, die den Spalten in einer Datenbanktabelle entsprechen (Quellcode 36).
Die Felder werden dabei als GroovyEigenschaften deklariert. Da im Projekt ein Student mehrere Studentenarbeiten haben kann, wird eine 1:nBeziehung implementiert. Assoziationen zwischen den DomainKlassen werden mit Hilfe der Schlüsselwörter hasMany und belongsTo beschrieben und als statisch deklariert.
Dadurch wird die Studentenarbeit zum Bestandteil (Aggregation) eines Studenten. Dies hat eine Auswirkung auf die DeleteFunktion. Wenn ein Student gelöscht wird, werden automatisch ihm gehörende Studentenarbeiten gelöscht. Innerhalb des constraintsBlocks werden die einzelnen Validierungsregeln aufgestellt (Quellcode 37).
69
$ grails create-domain-class Student $ grails create-domain-class Stwork
Quellcode 36: DomainKlasse Student
1 class Student { 2 String firstname 3 String lastname 4 Integer matnr 5 String faculty 6 String address 7 String email 8 static hasMany = [stworks:Stwork] 9 }
Quellcode 37: constraintsBlock des StudentDomainModells
1 class Student { 2 ... 3 static constraints = { 4 firstname(blank:false, size: 2..30, matches: '[A-z]+') 5 lastname(blank:false, size: 2..30, matches: '[A-z]+') 6 matnr(blank:false, min: 10000, max: 99999) 7 faculty(blank:false, size: 2..30) 8 address(blank:false, maxSize:1000) 9 email(blank:false, email:true) 10 } 11 }
6 Entwurf und Implementierung
Für jedes Attribut werden die Bedingungen deklariert. Die Anweisung blank:false definiert beispielsweise, dass eine Zeichenkette nicht leer sein darf. Bei der Datenbankschemagenerierung wird in diesem Fall ein not null auf das entsprechende Datenbankfeld gesetzt. Das Schlüsselwort matches ermöglicht die Nutzung von regulären Ausdrücken. Beispielsweise dürfen die Felder firsname und lastname nur aus „alpha numerischen Zeichen“bestehen. Außerdem muss die Länge von Feldern zwischen 2 und 30 Zeichen sein. Mittels der toStringMethode werden Referenzen zu anderen Objekten angezeigt. Standardmäßig zeigt Grails mit dieser Methode den Klassennamen und den Primärschlüssel an.
Die toStringMethode kann überschrieben werden. In diesem Fall wird eine Referenz auf den Vor und Nachnamen des Studenten bzw. auf den Titel der Studentenarbeit verwendet.
6.4.3 Implementierung des User Interfaces
Nach Anlegen der DomainModelle, kann man mit der Implementierung des UserInterfaces beginnen. Aufbauend auf einem bestehenden DomainModell bietet Grails die Möglichkeit, die Controller und die Views für grundlegende CRUDFunktionen automatisch zu erzeugen. Dies geschieht mit Hilfe des dynamischen Scaffolding. Als Erstes werden die Controller angelegt:
Um das dynamische Scaffolding zu aktivieren wird in dem Controller die scaffoldEingenschaft auf das entsprechende DomainModell gesetzt:
Es werden automatisch für beide Controller jeweils acht Aktionen (index, list, show, delete, edit, update, create, save) als Groovy Server PageDatei (GSP) unter grailsapp/views angelegt. Um aber den Quellcode der Views im Projektordner zu sehen, muss der Befehl grails generateall ausgeführt werden.
70
Quellcode 38: toStringMethode
1 class Student { 2 String toString(){ 3 "${this.lastname} ${this.firstname}" 4 ... 5 class Stwork { 6 String toString(){ title } 7 ...
$ grails create-controller Student $ grails create-controller Stwork
def scaffold = Student
6 Entwurf und Implementierung
Als Nächstes wird ein allgemeines Layout für die gesamte Beispielanwendung angelegt. In einem speziellen Verzeichnis grailsapp/views/layout wird die Datei main.gsp erstellt, die zur Aufnahme des Layout dient. In der Datei werden zwei Platzhalter für den Header und MainBereich definiert und im Fußbereich eine weitere TemplateDatei _footer.gsp eingebunden(Quellcode 39). Gleichzeitig wird die CSSDatei student.css in dem webapp/cssVerzeichnis angelegt.
Die PaginationFunktion6 ist in Grails sehr einfach realisiert. Die Methode wird dazu verwendet um die große Datenmenge in kleinere Abschnitte zu teilen. Die Definition findet in einem Controller statt. Mit dem maxParameter wird die maximal gewünschte Anzahl von Einträgen pro Seite festgelegt.
In einem View kann die Seitennavigation durch das paginateTag angezeigt werden. So kann man sich durch mehrere Seiten der Ergebnisliste bewegen. Die Filter werden in einem student/list.gspView als einfache Links realisiert:
6 http://www.grails.org/GSP+Tag++paginate
71
Quellcode 40: Die Definition einer paginateMethode
1 class StudentController { 2 def list = { 3 params.max = Math.min( params.max ? params.max.toInteger() : 4, 100) 4 [ studentInstanceList: Student.list(params), 5 studentInstanceTotal: Student.count() ] 6 } 7 ...
Quellcode 39: LayoutDatei
1 <html> 2 <head> 3 <g:layoutHead /> 4 </head> 5 6 <body> 7 <div class="banner"> 8 <div class="menu"> ... </div> 9 </div> 10 <div class="main"><g:layoutBody /></div> 11 <div class="footer"><g:render template="/footer" /></div> 12 </body> 13 </html>
<g:link id="woche" absolute="true"> Innerhalb einer Woche</g:link> <g:link id="monat" absolute="true"> Innerhalb eines Monats</g:link> ...
6 Entwurf und Implementierung
Jeder Filtereintrag erhält einen eigenen idParameter, durch den man im Controller erkennen kann welcher Link geklickt wurde. Die Logik wird im StudentController.groovy in der listAktion realisiert.
Im Controller wird dieser idParameter durch paramsHash übergeben. Ausgehend davon welcher Wert übergeben wird, wird die entsprechende Suchanfrage mit Hilfe der findAllMethode durchgeführt. Die findAllMethode realisiert so genannte dynamische Finder. Wird kein Parameter übergeben, wird die gesamte Liste der Datensätze ausgegeben. In dem listView wird vor dem Laden der Webseite überprüft, ob der params.idParameter übergeben wurde. Wenn ja, wird ein FilterTemplate _filter.gsp gerendert, sonst wird die Liste von den gesamten Studenten gerendert.
6.4.4 Suchfunktion mit Ajax
Grails bietet eine breite Unterstützung für die Entwicklung von AjaxAnwendungen über spezielle AjaxTags. Grails geht dabei einen sehr unkomplizierten Weg und vereinfacht damit die AjaxEntwicklung, da diese Tags von einigen JavaScriptBibliotheken wie Yahoo! Ui, Prototype oder Dojo unterstützt werden. Es müssen nicht eigene Ajax und JavaScriptFunktionalitäten entwickelt werden, sondern vorhandene JavaScriptBibliotheken können sehr einfach genutzt werden.
72
Quellcode 41: Definition des Filters im Controller
1 def list = { 2 def results 3 def today = new Date() 4 if ( params.id == "woche") { 5 params.max = Math.min(params.max ? params.max.toInteger() : 4,100) 6 params.offset = params.offset ? params.offset.toInteger() : null 7 results = Stwork.findAllByDefensedateBetween(today,today+7,params) 8 [stworkInstanceList: results, params: params ] 9 } 10 ... 11 else { 12 params.max = Math.min(params.max ? params.max.toInteger() : 4,100) 13 [studentInstanceList:Student.list(params), 14 studentInstanceTotal:Student.count()] 15 ...
Quellcode 42: Rendern der Templates
1 <g:if test="${params.id == 'woche'}"> 2 <g:render template="filter"/> 3 </g:if> 4 <g:else> 5 <g:render template="leftColumn"/> 6 </g:else>
6 Entwurf und Implementierung
Standardmäßig wird in Grails auf Prototype und Scriptaculous gesetzt. Prototype ist die Standardbibliothek von Ruby on Rails, sie ist relativ klein und schnell, mit einer sehr großen UserCommunity und benötigt keine Installation. Deshalb wurde bei dieser Aufgabe die PrototypeBibliothek eingesetzt. Die Bibliothek muss zuvor in das main.gspLayout eingebunden werden:
Grails bietet eine Reihe von AjaxTags7, wie remoteField, remoteFunction, remoteLink, formRemote, submitToRemote an, die über die AjaxSchnittstelle des Browsers verarbeitet werden können. Um die Suche mit AjaxUnterstützung zu realisieren, wird als Erstes ein Suchfeld mit Hilfe des <g:remoteField>Tags in die list.gspDatei eingebaut. Dieses Tag erzeugt ein InputFeld, welches seinen Inhalt bei Veränderung per Ajax an den Server sendet. Der Name des RequestParameters kann durch das Attribut paramName angegeben werden:
Das Tag löst normalerweise nach jedem eingetippten Zeichen einen AjaxAufruf aus, deshalb ist es sinnvoll, die Beschränkung hinzuzufügen, dass erst nach drei Zeichen ein Aufruf ausgelöst wird. Der Wert des Textfelds wird als Parameter mit Namen q an die GrailsAction search übermittelt. Das Resultat der Anfrage wird in einem <div>Element searchResult aktualisiert. Die zu diesem Aufruf passende Aktion sowie die Erzeugung der Antwort wird in der Aktion search implementiert. Hibernate kann genutzt werden um die einfache Suche zu realisieren, was aber sehr kompliziert zu erreichen ist, da die Suche durch alle Felder der DomainModelle durchgeführt werden muss. Am Einfachsten benutzt man ein Plugin namens searchable. Das Plugin wird mit dem Befehl installplugin searchable installiert und ermöglicht die Suche über beliebige Attribute einer oder mehrerer DomainKlassen:
7 http://www.grails.org/ajax
73
<g:javascript library="prototype" />
Quellcode 43: Suchfeld in der listDatei
1 <div id="search_box"> 2 <g:remoteField before="if (this.value.length < 3) return false;" 3 name="q" paramName="q" update="searchResult" action="search"/> 4 <div id="searchResult"></div> 5 </div>
Quellcode 44: DomainKlassen in den Suchbereich einbinden
1 class Student { 2 static searchable = [only: ['lastname', 'firstname']] 3 } 4 class Stwork { 6 static searchable = [only: ['artofwork', 'title']] 7 }
6 Entwurf und Implementierung
Dies bedeutet, dass die Suche in der Klasse Student nach dem Vor und Nachnamen des Studenten und in der Klasse Stwork nach der Art der Studentenarbeit und nach dem Titel durchgeführt wird. Als Nächstes wird im StudentController.groovy die searchAktion implementiert. Das Plugin stellt viele neue Methoden zur Verfügung, aber im Projekt wird nur seine searchMethode benutzt. Die searchMethode des searchablePlugins liefert ein SuchergebnisObjekt mit einer Teilmenge von Objekten zurück. Die Methode erhält den QParameter, die die Abfrage überprüft, ob diese nicht gleich Null ist.
In der Variablen searchResult werden die Suchergebnisse für das Student und StworkDomainModell zusammengebaut. Das Ergebnis wird dann an das Template student/_searchResult.gsp übergeben. Die Suche wird sowohl nach Studenten, als auch nach Studentenarbeiten durchgeführt. Wenn nach einem unvollständigen Begriffe gesucht werden muss, kann ein Stern am Ende des Begriffes hinzugefügt werden, um die Suche zu aktivieren:
6.4.5 Grails Authentifizierung
Da jede Beispielanwendung einen passwortgeschützten Bereich benötigt, wird in Grails dafür ein Spring Security(Acegi)Plugin8 benutzt. Das Plugin wird aus dem Projektverzeichnis mit dem Befehl grails installplugin acegi installiert.
8 http://grails.org/plugin/acegi
74
Quellcode 45: Implementierung einer searchMethode
1 def search = { 2 def q = params.q ?: null 3 def searchResults 4 if(q) { 5 searchResults=[studentResults:Student.search(q, [max:10]), 6 stworkResults:Stwork.search(q,[max:10]),q: q.encodeAsHTML()] 7 } render(template:"searchResults", model: searchResults) 8 }
Abbildung 6.6: Suchmöglichkeiten
6 Entwurf und Implementierung
Als Nächstes werden die User, Role und RequestmapDomainModelle erstellt. Es können dafür auch andere Namen benutzt werden, in diesem Fall ist es Person, Authority und Requestmap:
Die Klasse Person dient zur Darstellung der Benutzer in der Anwendung. Die Klasse Authority wird dazu benutzt, die Rollen und Rechte zu vertreten. Die RequestmapKlasse gibt an, welche BenutzerRollen mit welchen Maßnahmen verbunden sind. Für jede URL, die man sichern möchte, wird eine BenutzerRolle angegeben, für die der Zugriff auf die genannten URLs erlaubt ist (Abbildung 6.7).
Die erstellten DomainKlassen benötigen noch die Controller und die Views. Dies ist mit dem schon bekannten Befehl von Grails generateall möglich. Es ist auch möglich die AcegiTagLibs in den GSPViews zu nutzen. TaglibsFunktionen umfassen Methoden wie ifAllGranted, ifNotGranted, ifAnyGranted, loggedInUserInfo, isLoggedIn, isNotLoggedIn und loggedInUsername.9 Die AcegiTagLibs ermöglichen nicht nur die Informationen über den angemeldeten Benutzern in der Beispielanwendung zu zeigen, sondern auch den Zugriff auf einige Funktionen für die User und GastBenutzerrolle zu beschränken. Dies geschieht im mainLayout:
9 http://www.grails.org/AcegiSecurity+Plugin++Artifacts
75
$ grails create-auth-domains Person Authority Requestmap
Quellcode 46: Die Zugriffsbeschränkung für die User und GastBenutzerrolle
1 <g:isLoggedIn> 2 <g:ifAllGranted role="ROLE_USER"> 3 <g:link controller="person" action="index">Benutzerliste</g:link> 4 </g:ifAllGranted> 5 . . . 6 Sie sind als <g:loggedInUserInfo field="username"/>angemeldet. 7 </g:isLoggedIn>
Abbildung 6.7: RequestmapURL des adminBenutzer
7 Evaluierung
7 Evaluierung
In diesem Kapitel erfolgt die Evaluierung anhand der in Kapitel 5 definierten Kriterien. Die Evaluierung ist wie folgt aufgebaut: Zunächst werden in einer Kategorie einzelne Kriterien untersucht und bewertet. Sind Kriterien mit mehreren Unterpunkten zu vergleichen, werden alle Unterpunkte entsprechend bewertet und danach der Mittelwert gebildet. Die Gegenüberstellung der WebFrameworks erfolgt sowohl in tabellarischer Form als auch auf Basis kurzer textueller Zusammenfassungen. Anschließend werden besondere Vor und Nachteile eines jeden Frameworks noch einmal kurz diskutiert.
7.1 Funktionale Kriterien
7.1.1 Datenbank und Modelle
Alle drei Tools verwenden ein objektrelationales Mapping, um die Objekte in einer relationalen Datenbank abzubilden. In Rails wird als Erstes das Datenbankschema erstellt, wo die Tabellen und die Spalten definiert werden. Danach prüft die ModellKlasse die Spalten der TabellenDefinitionen um die zugehörigen Attribute zu bestimmen. Django und Grails gehen in diesem Fall einen anderen Weg. Als Erstes wird die ModellKlasse mit DatenAttributen in PythonCode definiert. Daraus werden die Spalten der Datenbanktabellen und das Datenbankschema erzeugt. Mit dem syncdbBefehl werden anschließend die Datenbank und die Tabellen aus dem Modell generiert. Grails hat die gleiche Vorgehensweise wie Django, nur die Änderungen an dem DomainModell werden bei jedem WebserverNeustart automatisch angepasst. Das Konzept von Django und Grails ist klarer und übersichtlicher als von Rails. Die wichtigsten Funktionalitäten der WebFrameworks zu diesem Punkt werden in Tabelle 6 gegenübergestellt.
Ruby on Rails Django Grails
DatenbankKonfigurationsdatei
YAMLDatei: database.yml
PythonDatei:settings.py
GroovyDatei: DataSource.groovy
Beziehungen 1:1, 1:n, n:m 1:1, 1:n, n:m 1:1, 1:n, n:m
ORM ActiveRecordKlasse ModelKlasse basiert auf Hibernate
0 0 ++
Unterstützte Datenbanken(DB)
DB2, Firebird, Frontbase, MySQL, Openbase, Oracle, PostgreSQL, SQLite, Sybase
SQLite3, MySQL, PostgreSQL, Oracle
Alle DB, die von Hibernate unterstützt werden. InMemoryDatenbak: HSQL
++ + ++
76
7 Evaluierung
Ruby on Rails Django Grails
ModellAttribute Das Modell ist in zwei Dateien definiert: in der MigrationsDatei und in der ModellKlasse.
Die MigrationDateien enthalten die ModellAttribute. In der ModellKlasse werden die Validierungsregeln und die Beziehungen zwischen den Tabellen definiert.
Alle Modelle mit Attributen und die zugehörigen Eigenschaften werden in einer einzigen models.pyDatei definiert.
Die ModellAttribute und die zugehörigen Eigenschaften werden in der DomainKlasse definiert. Jedes Modell wird in je einer Datei definiert.
0 + +
Namenskonvention
Der Name der Datenbanktabellen ist immer der Plural des Modellnamens. Die Spaltennamen sind gleich den AttributNamen.
Der Primärschlüssel wird immer automatisch erstellt und heißt id.
Bestehen die Tabellennamen, Variablennamen oder Dateinamen aus mehreren Wörtern, werden diese durch einen Unterstrich getrennt.
Der Name der Datenbanktabellen besteht aus zwei Teilen: Applikationsname und Modellname, die mit einem Unterstrich geteilt werden. Die Spaltennamen sind gleich den AttributNamen.
Der Primärschlüssel wird immer in jeder Tabelle automatisch erstellt und heißt immer id.
Bestehen die ModellAttribute aus mehreren Wörtern, werden diese durch einen Unterstrich geteilt.
Der Name der Datenbanktabellen ist gleich dem Modellnamen, die Spaltennamen sind gleich den AttributNamen.
Dieses Verhalten kann jederzeit in der mappingMethode der DomainModelle geändert werden.
+ + +
Validierung Die Validierung findet auf zwei Arten statt: durch die Nutzung von Klassenmethoden validates_XXX und durch Überschreiben der validateMethode.
Für jedes Datenfeld wird ein Name und ein Datentyp deklariert. Die Datentypen und dazu eingegebenen Parameter werden von Django zur Validierung von Objekten verwendet.
Innerhalb des constraintsBlocks in der DomainModellKlasse werden die einzelnen Validierungsregeln festgelegt.
+ 0 +
Datenbankabfragen
Finder: findMethodeDynamische Finder: find_by_XXX und find_all_by_XXXMethode
Die Kriterien werden automatisch durch den Methodennamen erkannt.
Es wird ein QuerySet in der ModellKlasse konstruiert, die eine Sammlung von Objekten aus der Datenbank darstellt.
all, filter, excludeMethoden
Finder: find und findAllMethodeDynamische Finder:findByXXX und findAllByXXXMethode
Ist sehr leistungsstarkes Werkzeug von Grails.
+ + ++
77
7 Evaluierung
Ruby on Rails Django Grails
Änderungen an der Datenbank
Rails verwendet Migrationen um die Datenbank zu ändern.
Migrationen ermöglichen den Wechsel zwischen verschiedenen Versionen des Datenbanksschemas.
Um die bestehende Datenbanktabelle zu erweitern, muss diese Tabelle gelöscht werden und dann mit dem syncdbBefehl wieder erstellt werden. Das fehlende Attribut in der Tabelle kann auch manuell hinzugefügt werden, ohne die bestehende Tabelle zu löschen.
Grails aktualisiert die Datenbanktabelle automatisch bei jedem WebserverNeustart. Der dbCreateParameter muss auf createdrop gesetzt werden.
Diese Funktion kann aber manchmal instabil sein.
++ 0 0
Pagination Die PaginationFunktion ist als Plugin realisiert. Ist leicht zu installieren und zu bedienen.
Die PaginationFunktion ist nur als Plugin möglich. Die Installation ist nicht sehr einfach, die Bedienung.
Ist im Kern des Frameworks integriert. Die Funktion hat allerdings Probleme, wenn nur ein Teil der Datensätzen aus der Datenbank ausgegeben werden muss.
++ 0 0
Bewertung 1,9 2,5 1,9
++ sehr gut + gut 0 ausreichend schlecht – sehr schlecht
Tabelle 6: Datenbank und Modelle
7.1.2 Controller
Der Controller übernimmt die Logik der WebAnwendung. Er nimmt die Anfragen (Requests) entgegen, greift auf einige Daten über die ModellKlasse zu, setzt und fragt die Cookies und Session ab, übernimmt die Verarbeitung der Variablen und generiert die Antworten (Responses) bzw. leitet die Daten (Modell) an die Views weiter. Aktionen werden als Eigenschaften eines Controllers definiert und werden mit gleichnamigen Views verbunden. In Rails und Grails sind dafür die ControllerKlassen verantwortlich. In Django wird durch seine MTVPattern die Funktionalität des Controllers von einem View übernommen. Jeder Controller verfügt über eine Anzahl vordefinierter Eigenschaften, die zur Laufzeit dynamisch mit Werten versorgt werden. Rails und Grails haben eine Reihe von solchen Parametern. Auf den RequestParameter greift der Controller über die paramsMethode zu. Status und FehlerMeldungen werden über die flashMethode definiert. Eine RailsAnwendung hat immer einen übergeordneten Controller, den ApplicationController, von dem alle anderen Controller erben. In dem ApplicationController werden meist die Hilfsmethoden definiert, auf die alle Controller der Anwendung zugreifen können. Eine Aktion in Django ist nur eine Funktion, die ein festes Argument aus einem request annimmt und einer optionalen Gruppe von benannten Argumenten zurück gibt.
78
7 Evaluierung
In anderen Funktionalitäten sind die Controller fast gleich. Es können keine wichtigen Unterschiede festgestellt werden. Deshalb werden alle WebFrameworks in diesem Punkt mit 2,6 bewertet.
7.1.3 URLRouting
Das URLRouting legt fest, welcher interne Aufruf aus der URL erfolgt. Rails und GrailsFramework benutzen das so genannte implizite Routing, d.h. dass der Aufruf eines konkreten Controllers oder einer Aktion aus der URL ermittelt wird. In Django kann man selbst angeben, über welche Adresse ein bestimmter Teil der Seite erreichbar sein soll. Dabei ist jeder View einzeln ansprechbar und kann mit einer beliebigen Adresse verknüpft werden. Jeder Adresse wird ein View zugeordnet. Dieses Konzept ist viel flexibler und liefert verständliche URLs. Zwischen beiden impliziten Konzepten von Rails und Grails, wirkt RailsRouting wesentlich leistungsstärker und überlegener als das URLMapping von Grails. Die wichtigsten Funktionalitäten des URLRoutings werden in Tabelle 7 zusammengefasst und bewertet.
Ruby on Rails Django Grails
URLKonfigurationsdatei
routes.rb urls.py UrlMappings.groovy
StandardRoutingKonfiguration
implizites URLRouting:controller/action/id'
explizites URLRouting Diese Philosophie wird „lose Kopplung“ genannt“. Dies bedeutet, dass die Teile sehr leicht zu tauschen sind.
implizites URLMapping:controller/action/id
0 ++ 0
RoutingRegeln erstellen
Solche eigenen Regeln können immer in die routes.rbDatei hinzugefügt werden, sollen aber oberhalb des Standardeintrags von Rails erfolgen.
Reguläre Ausdrücke können in RailsRouting wie auch in Django verwendet werden. Diese Funktionalität wird aber sehr selten benutzt und ist sehr schlecht dokumentiert.
Man kann selbst definieren, unter welcher Adresse welcher View angezeigt wird.
Jede Adresse besteht aus zwei Tupel. Der erste Eintrag ist ein so genannter Regex, der eine Adresse über einen regulären Ausdruck konfiguriert. In dem zweiten Eintrag wird ein verknüpfter View aufgerufen.
Solche eigenen Einträge können immer in die UrlMappings.groovyDatei hinzugefügt werden.
0 ++ 0
Bewertung 3 1 3
++ sehr gut + gut 0 ausreichend schlecht – sehr schlecht
Tabelle 7: URLRouting
79
7 Evaluierung
7.1.4 Templates
Die Templates definieren das Layout und die Formatierung von Daten, in die dynamische Inhalte eingebunden werden können. Es ist in der Regel so, dass, wenn ein Projekt in einem Team erstellt wird, die Templates nicht vom Programmierer, sondern vom Designer erstellt und bearbeiten werden. Deshalb ist Programmcode in Templates nicht zugelassen. Es ist eine sehr schlechte Vorgehensweise Logik in den Views zu implementieren, in Rails ist dies jedoch erlaubt. Die Templates von Django sind dagegen übersichtlicher für Designer, da Django keinen Programmcode im Template erlaubt. Außerdem scheint das TemplateSystem von Rails „primitiv“ zu sein, es wird in diesem Fall sehr oft auf alternative TemplateSysteme wie Liquid Templates1 oder HAML2 zurückgegriffen.
Die Elemente, die bei mehreren Seiten der WebAnwendung gleich aussehen, werden in ein zentrales Template, das so genannte Layout, ausgelagert. Die konkret benötigten Templates werden von den zentralen Template abgeleitet. Das DjangoTemplateSystem kann im Vergleich zu anderen mehrere Ebenen haben. In allen Frameworks können die Variablen zwischen verschiedenen Komponenten der Templates übergeben werden. Die einzelnen Funktionalitäten werden in Tabelle 8 zusammengefasst und bewertet.
Ruby on Rails Django Grails
TemplateEngine, TemplateDatei
ERBTemplates, *.html.erbXMLTemplates, *.rxmlRubyJavaScript(RJS)Templates, *.js.rjs
htmlSeite mit TemplatesTags, wo PythonCode definiert wird.
Java Server Pages (JSP),Groovy Server Pages(GSP)
Datenübergabe zwischen dem Controller und den Templates
Die dynamischen Inhalte im Controller, die in den Templates angezeigt werden sollen, werden in Instanzvariablen gespeichert, auf die die Templates zugreifen können.
Es wird von einem Controller ein HttpResponseObjekt an ein Template zurückgegeben, dem noch eine Reihe von Variablen, wie HttpRequestObjekt, hinzugefügt wird.
Jedem View wird von einem Controller ein Modell übergeben, damit der View eine Reihe von Variablen für die Darstellung verwenden kann.
TemplatesSprache
ERBTemplates ist ein Standard für Rails und enthält HTML mit eingebettetem RubyCode.
DjangoTemplate nutzt eine spezielle DjangoTemplateSprache.
GSP unterstützt traditionelle JSPSkriptletBlöcke und die eingebauten GSPTags.
0 + +
1 http://www.liquidmarkup.org/2 http://haml.hamptoncatlin.com/
80
7 Evaluierung
Ruby on Rails Django Grails
Layouts Die Layout Datei enthält einen <%= yield %> Bereich, in dem der Inhalt der Views geladen wird.
Wenn man ein anderes Layout als application.html.erb anwenden möchte, muss man dies im Controller über den Aufruf der layoutMethode deklarieren.
Unter TEMPLATE_DIRS in der settings.pyDatei muss definiert werden, wo die Templates im Projekt zu finden sind.
Das TemplateSystem unterstützt die Vererbung von Templates. Ein BasisTemplate wird mit dem {% extends %}Befehl zu einem abgeleiteten Template hinzugefügt. Mit Hilfe von {% block%}Befehl werden die Platzhalter innerhalb des BasisTemplate definiert.
Die LayoutDatei ist in dem grailsapp/views/layoutsVerzeichnis in der main.gspDatei definiert.
Das LayoutSystem ist auf einem SiteMeshFramework aufgebaut.
Ein typisches Layout stellt normalerweise drei Platzhalter: layoutTitle, layoutHead, layoutBody.zur Verfügung.
0 + 0
Formulare Rails unterstützt zwei Arten von Formularen: Formulare mit Bezug zu einem Modell und Formulare ohne Bezug zu einem Modell.
Rails stellt für Formulare viele HelperMethoden zur Verfügung, die das Erstellen von Formularen sehr einfach machen.
Die Formulare werden durch die django.formsBibliothek unterstützt.
Die Bibliothek übernimmt folgende Aufgaben: Automatische Generierung eines Formulars, die Validierung von Angaben, die Konvertierung der im Formular vorliegenden Datentypen in PythonDatentypen.
Grails unterstützt viele verschiedene Tags beim Umgang mit HTMLFormularen und Felder.
Das FormTag ist controller und aktionsbewusst. Dies bedeutet, dass man mit dem urlParameter festlegen kann, welcher Controller und welche Aktion die Angaben des Formulars bearbeiten wird.
+ + +
Partials Partials werden unterstützt. Der Dateiname beginnt mit einem Unterstrich.
Partials werden von Django nicht unterstützt.
Partials werden als Template unterstützt. Der Dateiname beginnt mit einem Unterstrich.
Bewertung 2,7 2 2,3
++ sehr gut + gut 0 ausreichend schlecht – sehr schlecht
Tabelle 8: Templates
7.1.5 Daten und Benutzer Verwaltung
Die beiden WebFrameworks Grails und Rails bieten für die DatenVerwaltung ein Werkzeug namens Scaffolding. Das Scaffolding bietet eine automatische Generierung der Controller und der Views für ein Modell. Diese dienen als temporäre Platzhalter, während man die Anwendung schrittweise aufbaut. In Grails ist noch das dynamische Scaffolding eingebaut, das in Rails ab Version 2 als Plugin existiert.
81
7 Evaluierung
Im Gegensatz zu denen hat Django die integrierte Administrationsoberfläche. Für jedes Modell erstellt das Framework automatisch eine AdministratorSeite, wo man die Elemente des Modells erstellen, ändern und löschen kann. Die Einträge können außerdem gefiltert, gesucht und sortiert werden. Es muss nur eine weitere admin.pyDatei angelegt werden, in der die Modellklassen hinzufügt werden. Als Ergebnis wird das StandardAdminInterface zur Verfügung gestellt.
Das DjangoAdminInterface ist sehr benutzerfreundlich. Es ermöglicht nicht nur die Verwaltung von Daten, sondern auch die Verwaltung von Benutzern, das Hinzufügen, Bearbeiten und Löschen der grundlegenden Berechtigungen für Benutzer. Es ist rudimentär, kann aber in vielen Fällen ausreichen. Die Operationen sind nur auf bestimmte Objekttypen beschränkt, nicht auf Attribute dieser Objekte. So kann man zum Beispiel dem Benutzer nicht die Erlaubnis erteilen, dass er nur die Einträge bearbeiten darf, die er angelegt hat. Das DjangoAdminInterface hat auch Nachteile. Sein Quellcode ist sehr schwer zu ändern. Entweder verwendet man den Quellcode, wie er ist, oder man benutzt ein Plugin. Diese Situation wird sich aber bald ändern, da die newformsadminBibliothek in die neue django.contrib.adminApplikation integriert wird. Wenn sie freigegeben wird, hat der Entwickler die Möglichkeit, das AdminInterface benutzerdefiniert zu ändern.
Rails und Grails haben kein AdminInterface in ihrer KernDistribution, im Gegensatz zu Django. Allerdings haben sie eine Reihe von Plugins, die das anbieten. Alle drei WebFrameworks unterstützen Sessions und Messaging. Allerdings bereinigen Rails und Django abgelaufene Sessions nicht automatisch. Man muss regelmäßig alte Sessions aus der Datenbank löschen.
Schlussfolgernd kann man sagen, dass alle drei WebFrameworks noch Verbesserungspotential aufweisen. Trotz gewisser Nachteile des DjangoAdminInterfaces ist es doch eine effektive Lösung für die Daten und BenutzerVerwaltung mit einer gewissen Trennung zwischen Frontend und BackendBereich. In einem öffentlichen Bereich werden die Inhalte der Webseite angezeigt, in einem AdministrationBereich hinzugefügt, geändert und gelöscht. Die wichtigsten Funktionalitäten werden in Tabelle 9 dargestellt und bewertet.
Ruby on Rails Django Grails
DatenVerwaltung DatenVerwaltung wird als ein statisches Scaffolding realisiert.
DatenVerwaltung ist in dem AdminInterface möglich.
DatenVerwaltung wird als dynamisches und statisches Scaffolding realisiert.
Bewertung 2,3 1,8 2,3
82
7 Evaluierung
Ruby on Rails Django Grails
BenutzerVerwaltung
Die BenutzerVerwaltung und die BenutzerAuthentifizierung sind durch die Nutzung von Plugins wie z.B. Restfulauthentication3 oder Acts as Authenticated4 möglich.Die BenutzerAuthentifizierung kann allerdings auch als eine HTTPAuthentifizierung eingesetzt werden. Dabei wird die authenticateMethode zur Verfügung gestellt.
Die DjangoAdminAnwendung hat auch eine grundlegende BenutzerVerwaltung, einschließlich der Verwaltung von Benutzern und Gruppen.
Die Administrationskonsole ist durch ein Passwort geschützt. Man kann einen SuperuserAccount generieren.
Die BenutzerVerwaltung und die BenutzerAuthentifizierung sind durch die Nutzung von Plugins wie Spring Acegi 5 oder Jsecurity 6 möglich.
Bewertung 2,4 2 2,6
++ sehr gut + gut 0 ausreichend schlecht – sehr schlecht
Tabelle 9: Daten und BenutzerVerwaltung
7.2 Dokumentation und ProjektCommunity
Die Dokumentation dient nicht nur dazu, das WebFramework kennen zu lernen, sondern stärkt auch die ProjektCommunity, hilft neue Mitglieder zu rekrutieren, fördert die Diskussion und sorgt für Dynamik im OpenSourceSoftware Projekt. Die DjangoDokumentation kann man als "Prosa"Dokumentation bezeichnen, sie ist sehr umfangreich und nicht für Anfänger geeignet. Bei solcher umfangreichen Dokumentation wird mehr Zeit verbraucht, um die notwendigen Information zu finden. Django besitzt außerdem kein APIReferenzHandbuch wie z.B. Rails oder Grails. Django und Rails haben übersichtliche OnlineHandbücher, was dem GrailsFramework noch fehlt. Die GrailsDokumentation ist leider sehr oft nicht vorhanden oder falsch geschrieben. Aber die Situation verbessert sich von Jahr zu Jahr.
Es gibt viele Wege, die Statistiken zu diesem Thema zeigen. Mit der Google Insights Search Graphen ist es möglich, die Häufigkeit der GoogleSuchbegriffe „rails, django, grails“ zu zeigen. In dieser Funktion lässt sich ein gewisser Trend über die Nutzung dieser drei WebFrameworks ermitteln (Abbildung 7.1).
3 http://agilewebdevelopment.com/plugins/restful_authentication4 http://agilewebdevelopment.com/plugins/acts_as_authenticated5 http://www.acegisecurity.org/6 http://www.jsecurity.org/
83
7 Evaluierung
Die Grafik stellt einen Vergleich zwischen den Suchvorgängen für einen bestimmten Begriff und der Anzahl aller Suchanfragen bei Google über einen bestimmten Zeitraum dar. Die Daten werden normalisiert und auf einer Skala von 0 bis 100 dargestellt. Jeder Kurvenpunkt in der Grafik wurde durch den Höchstwert oder 100 geteilt. So gibt es weitaus mehr Suchanfragen für Rails als für Django und Grails. Für Django und Grails steigen die Suchanfragen seit 2008 langsam aber kontinuierlich.
Besonders anschaulich ist die regionale Verteilung dieser drei Suchanfragen:
84
Abbildung 7.1: GoogleInsightsSearchFunktion
Abbildung 7.2: Die regionale Verteilung der Suchanfragen
7 Evaluierung
Rails und DjangoProjekte haben eine relativ große und aktive Community. Sie bieten selbst geschriebene Wikis, UserBlogs und Tutorials. Die RailsCommunity ist entschieden die größere von den drei Communitys. Gedruckte Bücher sind meistens ein Zeichen der Reife und Stabilität eines Projekts. Rails stellt mehrere gedruckte und elektronische Bücher zur Verfügung. Rails hat außerdem ausreichend Wiki und UserBlogSeiten, die schnell zur Lösung von spezifischen Problemen führen. Anderseits hat Grails sehr viele Tutorials, die sich gut für Anfänger eignen und für einen schnellen Einstieg sehr nützlich sind. Informationen für Fortgeschrittene bei spezifischen Problemen sind dagegen sehr schwer zu finden. Man kann sagen, dass die beiden Projekte Rails und Django aktiv und vital sind. Rails ist aber entwickelter und bedeutender als die anderen. Die GrailsCommunity ist noch nicht so groß und reif. In der Dokumentation muss noch sehr viel verbessert werden. Tabelle 10 gibt einen abschließenden Überblick über alle ausgearbeiteten Kriterien.
Ruby on Rails Django Grails
Dokumentation
Dokumentation, Tutorials ++ ++ 0
APIReferenzHandbuch ++ + ++
Bücher 7 ++ + 0
Wiki, UserBlogs ++ ++ 0
Bewertung 1 1,5 2,5
ProjektCommunity
Gegründet 2004 2005 2006
Aktuelle Version Rails 3(Stand: Feb.2010)
Django 1.2 alpha (Stand: Jan. 2010)
Grails 1.2 (Stand: Dez 2009)
GoogleGroup
Englisch 787 Gruppen 8 188 Gruppen 9 keine
GoogleGroup: rubyonrailstalk 10
Mitglieder: 20174
GoogleGroup:DjangoUsers 11:Mitglieder: 16555
Deutsch 14 Gruppen 8 Gruppen keine
Bewertung 1 1,5 4
++ sehr gut + gut 0 ausreichend schlecht – sehr schlecht
Tabelle 10: Dokumentation und ProjektCommunity
7 http://push.cx/2009/djangovsrailsthedeadtreeedition8 http://groups.google.com/groups/dir?lnk=nhpsfg&q=Rails&qt_s=Nach+einer+Gruppe+suchen9 http://groups.google.com/groups/dir?lnk=nhpsfg&q=Django&qt_s=Nach+einer+Gruppe+suchen10 http://groups.google.com/group/rubyonrailstalk11 http://groups.google.com/group/djangousers
85
7 Evaluierung
7.3 Support
7.3.1 Installation
Die Installation von allen drei WebFrameworks ist nicht sehr kompliziert. Die RailsInstallation beinhaltet mehr Komponenten, als die anderen WebFrameworks. Die Anbindung und die Konfiguration der Datenbank für die GrailsAnwendung war mit einigen Komplikationen verbunden. Die Ergebnisse werden in Tabelle 11 dargestellt.
Ruby on Rails Django Grails
Installieren einzelner Komponenten
Ruby, RubyGems, Rails, SVNClient
Es muss für Ruby eine passende RubyGemsVersion installiert werden.
In der LinuxDistribution ist Python meistens schon standardmäßig installiert.SVNClient,Django
JDK, Grails
+ ++ ++
Datenbankinstallation und Einbindung
Die Datenbankinstallation und die Einbindung sind ohne Probleme gelaufen.
Die Datenbankinstallation und die Einbindung sind ohne Probleme gelaufen.
Es sind einige Komplikationen mit der Datenbankeinbindung eingetreten.
++ ++
Konfigurationen des Projektes
Es sind keine Konfigurationen erforderlich.
Es sind viele Konfigurationen in der settings.py und , urls.pyDatei erforderlich.
Die DatenbankKonfigurationen sind in der DataSource.groovyDatei erforderlich.
++ + +
Verzeichnisstruktur
Alles im RailsVerzeichnis hat seinen Platz. Die Organisation ist klar und übersichtlich.
Rails hat aber keine Unterscheidung zwischen Projekt und Anwendung.
Das StandardVerzeichnis enthält nur ein Minimum an Dateien.
Django ermöglicht die Nutzung von mehreren Anwendungen oder Applikationen in einem Projekt, die zum Teil auf die gleichen Daten zugreifen können.
Die Organisation des ProjektVerzeichnisses ist sehr gut gegliedert.
Grails hat keine Unterscheidung zwischen Projekt und Anwendung.
+ ++ +
Bewertung 1,5 1,25 2
++ sehr gut + gut 0 ausreichend schlecht – sehr schlecht
Tabelle 11: Installation der WebFrameworks
86
7 Evaluierung
7.3.2 Entwicklungsprozess
Zu einem Entwicklungsprozess zählen folgende Unterpunkte: Debuggen, testgetriebene Entwicklung und IDE. Das Debuggen erleichtert sehr die Arbeit der Programmierer bei der Fehlersuche. Ein nützliches Werkzeug zum Debuggen ist der sogenannte Haltepunkt oder Breakpoint. Wenn die Applikation auf den Breakpoint trifft, wird die Applikation angehalten, und man kann in einer Konsole die Werte der Variablen überprüfen. Zu einem DebuggerTool gehören außerdem eine interaktive KommandozeilenKonsole, eine vom WebFramework generierte Fehlerseite und die LogDateien.
Alle drei Programmiersprachen Ruby, Python und Groovy sind InterpreterSprachen. Mit ihnen erstellte Programme werden oft als Skripte bezeichnet. Alle drei bieten einen KommandozeilenInterpreter, in dem man Skripte ausführen und die Ausdrücke zum Testen der WebAnwendung eingeben kann. Eine weitere gute Möglichkeit Fehler zu finden, ist die Fehlerseite, die von einem Framework geliefert wird. Tritt in einer WebAnwendung ein Fehler auf, kann das WebFramework eine Fehlerseite mit Details des Fehlers ausgeben. Man muss aber immer daran zu denken, dass die Fehlerseiten sicherheitsrelevante Informationen über die WebAnwendung enthalten und deshalb in der ProduktionsUmgebung deaktiviert werden müssen.
Das Einfügen von LogAnweisungen in den Code ist eine LowLewelMethode des Debuggens. Es kann auch der einzige Weg sein, weil der Debugger nicht immer verfügbar oder anwendbar ist. In der LogDatei werden sehr viele Informationen protokolliert, wie zum Beispiel welche URL aufgerufen wurde, welcher Controller und welche Aktion ausgeführt wurden. Das DjangoLogging kann durch ein PythonLoggingModul realisiert werden. Das PythonLoggingModul ist eine hervorragende Möglichkeit zum Hinzufügen der Protokollierung zu einer WebAnwendung.
Eine wirklich gute Möglichkeit Fehler zu erkennen, ist es, vorher zu testen. Bei der testgetriebenen Entwicklung wird zuerst der Code geschrieben um zu testen. Funktioniert der Test, wird dann der Programmcode geschrieben. Es sind allgemein folgende Tests bekannt:
• UnitTest wird verwendet um die Modelle zu testen.• IntegrationTest dient zum Testen der Gesamtfunktionalität der Applikation.• FunctionalTest verwendet man um die Controller und Views zu testen.
Rails unterstützt alle diese Tests. Außerdem werden von Rails noch so genannte PerformanceTests unterstützt. Die wichtigsten Funktionalitäten werden in Tabelle 12 gegenübergestellt und bewertet.
87
7 Evaluierung
Ruby on Rails Django Grails
KommandozeilenInterpreter
Interactive Ruby Shell irb Python Interpreter, ipython GroovyShell
Debugging, Breakpoints
Ab Rails 2.0 ist der RubyDebugger in Rails enthalten. RailsDebugger unterstützt unter anderem Breakpoints.
Django hat einen PythonDebugger (pbd). Damit können Breakpoints gesetzt werden, die Variablen untersucht und die Funktionen schrittweise ausgeführt werden.
Grails hat sehr unreife Debugger, es ist sehr schwierig in Grails zu debuggen.
Debuggen ist als DebugPlugin oder in einer IDE möglich
+ +
Fehlerseiten Es wird sehr wenige Fehlerinformation ausgegeben.
Django hat sehr gute und informative Fehlerseiten.
Es wird sehr wenige Fehlerinformation ausgegeben.
0 ++ 0
LogDatei Standardmäßig werden drei LogDateien angelegt: log/development.log, log/production.log, log/test.log.Mit Hilfe des loggerObjekts kann man aus einem Controller oder einem Modell heraus auch einen Eintrag in der LogDatei vornehmen.
Sehr gute Funktionalität wird durch das PythonLoggingModul12 angeboten, das als PythonStandardBibliothek realisiert ist.
Es steht auch ein Plugin namens djangologging13 zur Verfügung.
Grails nutzt ein sehr starkes Apache LoggingSystem namens Log4j. Die wichtigsten Einstellungen werden in der Config.groovyDatei vorgenommen.Diese Datei ermöglicht eine separate loggingKonfiguration für drei Umgebungen.
+ + +
Testgetriebene Entwicklung
Rails unterstützt Unit, Functional, Integration und PerformanceTests.
Die StandardPythonModule Doctests und Unit tests sind in Django eingebaut. Bei dem Doctest laufen einige Tests einer Methode in der interaktiven Konsole und anschließend werden die Ergebnisse in das Programm als docstringKommentare hinzugefügt.
Grails umfasst Unit, Integrations und FunktionalTests.
+ + +
IDE Aptana, Eclipse, IntelliJ IDEA, NetBeans, TextMate, Vim
Die Entwicklung mit Django wird zur Zeit durch keine IDE unterstützt.
NetBeans 6.5, IntelliJ IDEA, Eclipse, Tool Suite, TextMate
+ +
Bewertung 2,2 2,2 2,6
++ sehr gut + gut 0 ausreichend schlecht – sehr schlecht
Tabelle 12: Entwicklungsprozess
12 http://docs.python.org/library/logging.html13 http://code.google.com/p/djangologging/wiki/Overview
88
7 Evaluierung
7.3.3 Ajax und PluginSupport
Ruby on Rails hat eine vollständige und hervorragende AjaxUnterstützung. Die StandardBibliotheken wie Prototyp und Script.aculo.us sind schon im RailsFramework integriert. Die AjaxFunktionalitäten können in der Datei mit dem RubyCode einfach hinzugefügt werden, ohne Kenntnisse von JavaScript zu haben. Django hat bis jetzt noch keine standardisierte JavaScriptBibliothek und es ist nicht geplant ein Tool zu wählen oder zu standardisieren. Man kann ein beliebiges AjaxTool in der DjangoAnwendung integrieren. Die DjangoEntwickler haben öffentlich erklärt, dass JavaScript wie HTML und CSS als grundlegende Technologien zu betrachten sind und von jedem WebEntwickler zu beherrschen sind. Es gibt sehr viele Tutorials, die zeigen und erklären, wie man in Django mit Ajax umgehen kann, zum Beispiel unter [DjAjax]. Grails bietet eine Unterstützung für die Entwicklung von AjaxAnwendungen über spezielle AjaxTags, was die AjaxEntwicklung sehr vereinfacht. Diese AjaxTags werden von vielen JavaScriptBibliotheken wie Yahoo! Ui, Prototype oder Dojo unterstützt. Standardmäßig wird in Grails auf Prototype und Scriptaculous gesetzt, aber es ist jederzeit möglich weitere JavaScriptBibliotheken einzubinden.
Erweiterungen werden in Rails und Grails als Plugins und in Django als Applikationen realisiert. Die RailsCommunity produziert Plugins in unglaublichen Maße, und selbst wenn nicht alle von ihnen hohe Qualität haben, gibt es eine große Auswahl. RailsPlugins sind einfach zu installieren und zu konfigurieren. Dabei wird der Code aus einem SubversionRepository über das Internet installiert und ins vendor/pluginsVerzeichnis abgelegt. Es gibt auch eine sehr große OnlineDatenbank mit Plugins für Rails [RailsPlug2]. Ab 02. Februar 2010 stehen 1.505 RailsPlugins zur Verfügung. Grails hat die gleiche Vorgehensweise bei der Installation der Plugins wie Rails. Die Plugins werden sehr leicht mit dem installpluginBefehl installiert und in das webapp/pluginsVerzeichnis abgelegt. Allerdings ist die Auswahl nicht so groß wie bei Rails. Die Liste der GrailsPlugins wird auf der offiziellen Webseite von Grails gepflegt [GrPlugins]. DjangoApplikationen haben eine komplizierte Installation. Die Installation kann für jede Applikation verschieden sein, man muss immer strikt genau den InstallationAnweisungen zu jeder Applikation folgen. Die Applikationen werden auf der offiziellen Webseite von Django gepflegt [DjRes]. DjangoPluginSupport ist aber nicht so gut organisiert wie von Rails oder Grails, aber die Situation verbessert sich sehr schnell. Zusammenfassend kann man sagen, dass das RailsFramework eine beeindruckende Zahl von Plugins mit guter Qualität hat. Außerdem hat Rails eine hervorragende AjaxUnterstützung. Sehr enttäuschend ist es, dass Django die beschränkte Infrastruktur und Menge von Applikationen zur Verfügung stellt. Deshalb wird Rails in diesen beiden Punkten mit höheren Noten als die beiden anderen bewertet.
89
7 Evaluierung
Die Ergebnisse der Bewertung werden in Tabelle 13 dargestellt.
Ruby on Rails Django Grails
AjaxUnterstützung 1 1,8 1,5
PluginSupport 1 3 1,5
Tabelle 13: AjaxUnterstützung und PluginSupport
7.3.4 DeploymentSupport und Webhosting
An die Webanwendungen in Produktion werden andere Anforderungen gestellt, als für die Entwicklung. Die entscheidende Rolle spielen die Performance der Webanwendung und die Behandlung von vielen konkurrierenden Zugriffen. Der Prozess, die WebApplikation auf einem ProduktionsServer zu installieren und zu konfigurieren, wird Deployment genannt. Im Normalfall ist Deployment ein an sich ständig wiederholender Prozess, bei dem die Entwicklung und Auslieferung einer Webanwendung im Laufe der Zeit viele DeploymentZyklen durchläuft. Man muss für jeden neuen DeploymentZyklus zuerst eine neue Version der Webanwendung aus dem RCS, wie zum Beispiel Subversion, auschecken, diese dann manuell auf die Betriebsserver kopieren und anschließend die Webserver bzw. FastCGIProzesse von Hand neu starten.
Das Deployment von RailsAnwendungen kann mit Hilfe eines voll automatisierten DeploymentTools namens Capistrano realisiert werden. RailsDeployment mit Capistrano ist sehr gut in [RapWeb07] erläutert. Capistrano ermöglicht die Auslieferung einer neuen Version des Projektes und den Neustart der beteiligten Serverprozesse. Das Tool verwendet SSH, um mit dem Server zu kommunizieren. Capistrano geht davon aus, dass der Code in einem QuellcodeRepository gespeichert ist. Sobald das Deployment fertig ist, ist die Webanwendung sehr leicht aus einem EntwicklungsRepository zu aktualisieren.
Das DeploymentProblem bei Django wird unterschiedlich und nur unvollständig gelöst. Das derzeit empfohlene Deployment bei Django ist Apache und mod_python, obwohl es keinen Grund gibt, warum nicht FastCGI oder sogar ein anderer Server wie Lighttpd verwendet wird. So ein DeploymentTool wie Capistrano gibt es bei Django noch nicht. Das Deployment einer GrailsWebanwendung ist sehr einfach. Als Erstes wird die GrailsWebanwendung als Web Application Archive (WARDateien) mit dem grails warBefehl erstellt. Dadurch wird eine WARDatei im Hauptverzeichnis des Projekts erstellt, die dann auf jedem beliebigen Java EE Server bereitgestellt werden kann.
90
7 Evaluierung
Bevor man aber die WebApplikation veröffentlicht, benötigt man einen Webserver, auf dem die notwendige Serversoftware installiert sein muss. Es werden drei Arten von Webhosting berücksichtigt: ein HostingService, Virtueller Server (VPS) und dedizierter (root) Server. Viele Benutzer bevorzugen es, einen HostingService zu nutzen. Im Gegensatz zu PHP sind HostingAngebote für Rails, Django oder Grails selten. Es wird allerdings mehr Webhosting für Rails angeboten als für Grails und Django [vgl. Anhang D DeploymentSupport undWebhosting].
Da die Auswahl an WebhostingAnbietern sehr klein ist, ist es wahrscheinlich eine gute Idee einen eigenen Server zu mieten. Dies ist in zwei Varianten als virtueller und dedizierter Server möglich. Ein virtueller Server wird zwischen mehreren Kunden geteilt. Jeder Kunde hat allerdings einen abgeschlossenen Bereich mit eigenem LinuxBetriebssystem und eigenem RootZugang. Ein großer Vorteil bei dieser Lösung ist der niedrige Preis, der Hauptspeicher ist aber meist sehr begrenzt. Bei der anderen Variante wird ein Server nur für einen Kunden zur Verfügung gestellt. Der Preis ist dann höher, als bei einem virtuellen Server, da der Kunde für Hardware, den Stellplatz und für die Stromversorgung bezahlen muss. Man muss aber daran denken, dass ein solcher Server immer mit mehr Arbeit, wie Konfigurationen, Wartung und Sicherheit verbunden ist. Außerdem setzt diese Lösung mindestens Grundkenntnisse in UNIX oder Linux voraus.
Zusammenfassend kann man sagen, dass, im Gegensatz zu PHP, die HostingAngebote für Rails, Django oder Grails sehr gering sind. Die bevorzugte Lösung, besonders für die Django und GrailsAnwendungen, ist es, einen eigenen Server zu mieten. Tabelle 14 gibt einen abschließenden Überblick über diese beiden ausgearbeiteten Kriterien.
Ruby on Rails Django Grails
Deployment Deployment: Capistrano Anforderungen: Ruby, Rails, Rake, Subversion, sshd.Webserver: LightTPD mit FastCGI, Apache mit FastCGI (für die kleinen Projekte)
Anforderungen: Python 2.3;Webserver: Apache mit mod_python (FastCGI)Datenbank: SQLite, MySQL. PostrgeSQL
Anforderungen: JSP/Servlets, JVM;Webserver: TomcatDatenbank: SQLite, MySQL. PostrgeSQL
Webhosting Es werden mehr HostingServices angeboten als für Django oder Grails, aber immer noch wenig im Gegensatz zu PHP.
Webhosting wird nur im geringsten Maße angeboten.
Die Liste der verfügbaren HostingServices: [DjWH]
Es ist sehr schwierig einen HostingService zu finden. Die bevorzugte Variante ist einen eigenen Server zu mieten.Die Liste von möglichen Providern: [GrHost]
Bewertung 2 2,8 3,5
++ sehr gut + gut 0 ausreichend schlecht – sehr schlecht
Tabelle 14: DeploymentSupport und Webhosting
91
7 Evaluierung
7.4 Entwicklungseffizienz
In der Kategorie Entwicklungseffizienz werden zwei Kriterien überprüft: Implementierungszeit und Codeeffizienz. Unter Implementierungszeit wird die Zeit für die Umsetzung der Beispielanwendung und die relative Geschwindigkeit der Entwicklung verstanden. Die Implementierungszeit für einzelne Komponenten der Beispielanwendung wird in Tabelle 15 abgerechnet.
Ruby on Rails Django Grails
Projekt anlegen und konfigurieren
Keine Konfigurationen bei der Erstellung des Projektes notwendig.
Die Konfigurationen werden in der settings.py und in der urls.pyDatei vorgenommen.
Keine Konfigurationen bei der Erstellung des Projektes notwendig.
00:10:00 00:20:00 00:10:00
Datenbank(DB) anlegen und konfigurieren
Die Konfigurationen werden in der database.ymlDatei vorgenommen.
Es ist keine InMemoryDatenbank vorhanden.
Die Konfigurationen werden in der settings.pyDatei vorgenommen.
Es ist keine InMemory Datenbank vorhanden.
Die Konfigurationen werden in der DataSource.groovyDatei vorgenommen.
Vorher muss aber der Datenbank Treiber im Projektordner abgelegt werden.
00:15:00 00:10:00 01:40:00
Modelle anlegen Modelle werden mit ruby script/generateBefehl generiert.
Die Modelle werden in der Migrationsdatei um die einzelnen Attribute erweitert.
Modelle werden per Hand angelegt.
Mit dem syncdbBefehl werden die Modelle aktualisiert.
Modelle werden automatisch bei der Projekterstellung angelegt.
Wird der Webserver gestartet, werden die Modelle automatisch aktualisiert.
01:10:00 00:15:00 00:12:00
Startseite und Basisseiten (Grundgerüst)
Das Grundgerüst wird mit Hilfe eines ScaffoldGenerators angelegt.
Da kein ScaffoldGenerator vorhanden ist, werden die Start und Basisseiten per Hand angelegt.
Das Grundgerüst wird mit Hilfe eines ScaffoldGenerators angelegt.
09:30:00 14:00:00 08:00:00
Suchfunktion mit AjaxUnterstützung
Das PrototypeFramework muss nur in der LayoutDatei eingebunden werden.
Das Framework ist sehr leicht zu erlernen.
Das jQueryFramework muss installiert und eingebunden werden.
Zeit für das Erlernen des Frameworks muss berücksichtigt werden.
Das PrototypeFramework muss nur eingebunden werden.
Das searchablePlugin wird für die eigentliche Suche eingesetzt.
06:00:00 10:00:00 04:00:00
92
7 Evaluierung
Ruby on Rails Django Grails
Paginate Die Funktion wird alswill_paginatePlugin angeboten.
Die Funktion wird als PaginatePlugin angeboten.
Es hat bei der Installation einige Komplikationen auftreten.
Die Funktion ist schon in Grails integriert.
Bei der Nutzung der PaginateFunktion mit Filtern hat es einige Komplikationen geben.
02:00:00 03:30:00 06:00:00
FilterFunktion Die FilterFunktionen müssen implementiert werden.
Die FilterFunktionen sind schon im AdminInterfacevorhanden.
Die FilterFunktionen müssen implementiert werden.
06:00:00 00:00:00 04:00:00
AdminInterface Wird durch RestfulAuthenticationPlugin realisiert. Zeit für das Erlernen des Plugins muss berücksichtigt werden.
Wird beim Anlegen des Projektes automatisch erstellt, muss noch dem ProjektLayout angepasst werden.
Wird durch AcegiPlugin realisiert. Zeit für das Erlernen des Plugins muss berücksichtigt werden.
08:30:00 03:25:00 06:30:00
Einarbeitungszeit 16:00:00 19:00:00 21:00:00
HTMLSeiten,Layout
04:00:00
Insgesamt: 49:35:00 50:40:00 50:32:00
Die Zeiten sind in Form: Stunden:Minuten:Sekunden angegeben.
Tabelle 15: Implementierungszeit
Daraufhin kann man sagen, dass mit allen WebFrameworks ungefähr die gleiche Zeit gebraucht wurde, um die Beispielanwendung zu entwickeln (Abbildung 7.6).
93
Abbildung 7.3: Implementierungszeit
Ruby on Rails Django Grails
00:00
12:00
00:00
12:00
00:00
12:00
16:00 19:00 21:00
01:3500:45
02:0209:30
14:00 08:0006:00
10:00
04:0006:00 04:0002:00
03:3006:00
08:3003:25 06:30
AdminInterfacePaginateFilterFunktionSuchfunktionStartseite/BasisseitenProjekt/DB/Modelle Einarbeitungszeit
7 Evaluierung
Für die Entwicklung von Start und Basisseiten wurde mit Django mehr Zeit erbracht im Vergleich zu Rails und Grails. Bei der Entwicklung des AdminInterfaces wurde allerdings wieder Zeit eingespart. Grails braucht lange Einarbeitungszeit um die Konzepte und die Programmiersprache zu verstehen. Aber Grails besitzt sehr viele AnfängerTutorials, die den Einstieg erleichtern. Hier wurde allerdings die subjektive Implementierungszeit gemessen. Bei jedem anderen Entwickler können die Zahlen ganz anders sein.
Die Codeeffizienz wird durch einen quantitativen Vergleich bestimmt. Es werden alle per Hand geschriebenen Zeilen berücksichtigt. Leeren Zeilen, Kommentare und die automatisch generierten Zeilen werden nicht mitgezählt.
Codeeffizienz Ruby on Rails Django Grails
Modelle 26 31 45
Controllers (ViewDjango) 91 42 80
Templates 178 236 172
SchemaMigration 15
Authentication 60 5 62
Insgesamt: 370 314 359
Tabelle 16: Codeeffizienz
Abbildung 7.4 verdeutlicht noch einmal die Ergebnisse Tabelle 16. Bei der Entwicklung mit Django wurden allgemein weniger Codezeilen gebraucht als bei den anderen beiden WebFrameworks, obwohl deutlich mehr Zeilen für die DjangoTemplates entstanden.
94
Abbildung 7.4: Codeeffizienz
Ruby on Rails Django Grails
0
50
100
150
200
250
300
350
400
26 31 45
9142
80
178236
172
15
60
562
Authentication Schema Migration TemplatesControllersModell
7 Evaluierung
7.5 Sonstige Kriterien
7.5.1 Programmiersprache
Es ist sehr schwer, objektiv zu entscheiden, welche Programmiersprache gut oder schlecht ist. Es ist vor allem eine Frage des persönlichen Empfindens. In Tabelle 17 wird die Anwesenheit von bestimmten Funktionalitäten für drei Programmiersprachen dargestellt.
Ruby Python Groovy
Vorgestellt 1995 1991 2003
Aktuelle Version Version 1.9.1 (01.2009) Version 3.1.1 (08.2009) Version 1.7.0 (12.2009)
Objektorientirung Alle Datentypen sind Objekte.
In Python ist alles ein Objekt; Klassen, Typen, Methoden, Module etc.
Alle Datentypen sind Objekte.
Bibliotheken Die Bibliotheken sind vorhanden.
Umfangreiche StandardBibliothek von Python.
Umfangreiche StandardBibliothek von Java.
Syntax Hat eine besonders kompakte, gut leserliche und leicht zu lernende Syntax.
Ist syntaktisch eine sehr einfache, flexible, reife und klare Sprache.
Syntax ist leicht zu lesen und zu verstehen.
Typisierung dynamische Typisierung
Ruby typisiert Variable dynamisch zur Laufzeit.
Die Variablen haben keinen Typ. sie sind nur Platzhalter, Daten dagegen besitzen einen Typ. Variable müssen auch nicht deklariert werden, sondern sie werden durch die erste Benutzung erzeugt.
dynamische Typisierung
In Python ist der Datentyp an das Objekt gebunden und nicht an eine Variable, d.h. Datentypen werden dynamisch vergeben.
Alle Werte werden per Referenz übergeben.
statische und dynamische (statische Typisierung ist optional)
NachteileSchwächen
Ruby unterstützt derzeit kein Unicode und UTF8 nur zum Teil.
Einige in anderen Sprachen gebräuchliche Kontrollstrukturen, wie do/while, sind in Python nicht vorhanden.
Keine Unterstützung für Fortsetzungen (continuations) und kein Support für Generatoren.
Verbreitung Ruby ist zur Zeit die am weitesten verbreitete Programmiersprache von diesen (Abbildung 7.5) obwohl sie bis 2004 fast nur in Japan verbreitet wurde.
Python wird im Gegensatz zu den beiden anderen nicht nur für die WebAnwendungen genutzt. Außerdem ist Python auch für die meisten gängigen Betriebssysteme frei erhältlich.
Groovy ist noch eine ganz junge Programmiersprache. Sie ist zur Zeit noch nicht so weit verbreitet wie Ruby oder Python.
Bewertung 1,8 1,4 2,4
++ sehr gut + gut 0 ausreichend schlecht – sehr schlecht
Tabelle 17: Programmiersprachen
95
7 Evaluierung
Mit den GoogleInsightsSearchGraphen ist es möglich die Häufigkeit von GoogleSuchanfragen für die Begriffe „python, ruby, groovy“ zu zeigen. Aus dem Funktionsverlauf lässt sich ein gewisser Trend über die Nutzung der drei Programmiersprachen ermitteln.
Aufgrund von Internetstatistiken kann man feststellen, dass im Februar 2010 Python fast etwa genau so häufig verwendet wurde wie Ruby und zehnmal häufiger als Groovy. Rails wird aber drei mal mehr als Django und zehnmal mehr als Grails eingesetzt [vgl. Dokumentationund ProjektCommunity]. Aus perspektivischen Gründen und eigenen subjektiven Erfahrungen wird der PythonProgrammiersprache die Note 1,4, der Programmiersprache Ruby 1,8 und der Programmiersprache Groovy 2,4 gegeben.
7.5.2 Security
Ein wichtiger Punkt ist es, die WebAnwendungen vor Angriffen zu schützen. SecurityProbleme treten in der Regel aufgrund von der Naivität oder Fehler der WebEntwickler auf. Jeder WebEntwickler muss die Sicherheit als wesentlichen Aspekt seiner Arbeit betrachten. Leider stellt sich heraus, dass dies ein sehr komplizierter Prozess ist. Dem Angreifer genügt es nur eine einzige Schwachstelle in der WebAnwendung zu finden, der Verteidiger dagegen muss jede einzelne von ihnen schützen. Es ist jedoch nicht das Ziel dieser Arbeit jede bekannte Schwachstelle in der WebAnwendungen in einer umfassenden Weise zu erklären. Es geht darum, die Sicherheitsprobleme kurz zusammen zu fassen und zu zeigen wie die WebFrameworks damit umgehen. In Rahmen dieser Arbeit werden vier AngriffsArten betrachtet: SQLInjection, CrossSiteScripting, CrossSiteRequestForgery und SessionsAngriffe. Die genaue Informationen zu diesen AngriffsArten sind im Anhang E Security zu finden.
96
Abbildung 7.5: Die Verbreitung von Programmiersprachen
7 Evaluierung
Es ist sehr wichtig, zu verstehen, was für Fehler das sind und wie man die Code der Anwendung verbessern und die Sicherheit erhöhen kann. Eine allgemeine Lösung ist es, unter keinen Umständen den Daten aus dem Browser zu vertrauen. Alle Daten jeglicher Art wie HTTPHeader, Cookies oder andere HTTPRequests, die aus dem Browser heraus kommen, müssen immer geprüft werden.
Alle drei WebFrameworks schützen automatisch vor StandardFehler der Entwicklung und verhindern automatisch die meisten bekannten AngriffsArten. Grails kann man extrem sicher nennen. Es ist weitestgehend immun gegen den gemeinsamen Pufferüberlauf und ungültige URLs. Die DjangoAnwendungen sind automatisch vor vielen StandardFehler der Entwicklung geschützt, die die Sicherheit der WebAnwendungen verringern.
Die Sicherheit kann auch auf die Berechtigungen für den Zugriff auf bestimmte Bereiche der WebAnwendung oder spezielle Inhalte weitergeleitet werden. Dies ist auf die Verwaltung von Benutzern bzw. Gruppen und Berechtigungen zurückzuführen. Die Sicherheitsvorschriften müssen sich auch auf die Authentifizierung der Benutzer beziehen. Auch hier hat Django im AdminInterface eine Standardauthentifizierung. Rails und Grails haben nur die separaten Plugins. Alle drei unterstützen verschlüsselte Passwörter. Die wichtigsten Punkte zu diesem Kriterium werden in Tabelle 18 zusammengefasst.
Ruby on Rails Django Grails
SQL Injection ActiveRecordMethoden übernehmen automatisch die Maskierung aller Metazeichen. Allerdings nur wenn keine conditionsBedingungen benutzt werden. Sobald man conditionsBedingungen oder eigene SQLAbfragen formuliert, muss man darauf achten, dass die Metazeichen maskiert sind.
Django maskiert automatisch alle speziellen SQLParameter.
In Hibernate, die eine zugrunde liegende Technologie von GORM ist, werden die Daten bei der DatenbankAbfrage automatisch maskiert.
Alle StandardDatenbankAbfragen via GORM verhindern automatisch SQLInjectionAngriffe.
CrossSiteScripting (XSS)
Rails stellt die hMethode zur Verfügung. Alle HTMLMetazeichen in Benutzereingaben oder Variablen, die an der Oberfläche ausgegeben werden, werden in HTMLEntities umgewandelt.
Das DjangoTemplateSystem maskiert automatisch alle variablen Werte.
Das Problem wird von Grails durch das SpringWebFlowModul14 gelöst.
Die encodeAsHTMLMethode überprüft alle DatenWerte aus Views auf Korrektheit.
14 http://opensource.atlassian.com/confluence/spring/display/WEBFLOW/Home
97
7 Evaluierung
Ruby on Rails Django Grails
CrossSite Request Forgery (CSRF/XSRF)
Ab Rails 2.0 ist das CSRFkillerPlugin in Rails integriert.
Das Plugin erzeugt für alle in Rails generierten Formulare einen SecurityToken, der über ein verstecktes Feld übertragen wird.
Django hat ein eingebautes Werkzeug, um vor dieser Art von Angriffen zu schützen.
Grails hat keine eigenen Mittel dafür. CSRFSchutz kann nur als Plugin eingesetzt werden, z.B. Jsecurity.
SessionsAngriffe
Sessions werden in Rails 2 in Cookies gespeichert, die mit einem HashWert vor Fälschung geschützt sind.
Django erlaubt nicht, in der URL die Sessionen zu übertragen.
Der Schutz gegen SessionAngriffe ist in Grails nur durch Plugins, wie Spring oder Security, möglich.
Bewertung 2,6 3 3
++ sehr gut + gut 0 ausreichend schlecht – sehr schlecht
Tabelle 18: Security
7.5.3 JobPerspektiven
In den vergangenen Jahren haben sich die JobPerspektiven für RailsEntwickler rapide verbessert. In Tabelle 19 Tabelle wird die Anzahl von Stellenangeboten der bekanntesten JobSuchmaschinen für die Suchbegriffe: „Ruby on Rails“, „Django“ und „Grails“ in Deutschland und in den USA dargestellt.
Job Trends. Stand: 20.01.2010 Ruby on Rails Django Grails
Bundesweit
monster.de 36 4 5
jobpilot.de 29 4 4
indeed.de 52 9 11
USA
indeed.com 7419 461 338
Bewertung 2,3 3,5 3,3
Tabelle 19: JobAngebote in Deutschland und in den USA
Die GrailsGemeinde ist viel kleiner als die von Rails oder Django, aber in Deutschland stehen im Gegensatz zu den USA sogar mehr Grails als DjangoStellenangebote zur Verfügung. Es stehen zum Beispiel in Deutschland deutlich mehr RailsJobangebote als Grails bzw. DjangoJobAngebote zur Verfügung (Abbildung 7.6).
98
7 Evaluierung
Mit dem EmploymentTrendWerkzeug der SimplyHiredJobSuchmaschine kann die Häufigkeit von Berufsbezeichnungen, Unternehmen, Fähigkeiten und Industrie auf dem USArbeitsmarkt verglichen werden (Abbildung 7.7). Der gleiche Vergleich auf dem deutschen Arbeitsmarkt konnte leider nicht gefunden werden.
Diese Grafik zeigt den Anteil der Arbeitsplätze mit den Begriffen „Rails“, „Django“ oder „Grails“ in den JobInseraten. Seit Juli 2008 hat sich die Anzahl der Arbeitsplätze für alle drei Frameworks erhöht. Die schnellste WachstumsTendenz ist aber für GrailsArbeitsplätze zu beobachten.
99
Abbildung 7.7: Job Trends für Rails, Django, Grails in den USA
Abbildung 7.6: JobAngebote in Deutschland [Stand: Jan.2010]
Ruby on Rails Django Grails
0
20
40
60
80
100
120
140
36
4 5
29
4 4
52
9 11
indeed.dejobpilot.demonster.de
7 Evaluierung
7.6 Ergebnisse der Evaluierung
In dieser Arbeit wurden drei WebFrameworks vorgestellt und anhand einer Beispielanwendung untersucht und verglichen.
Im Folgenden wird nun eine zusammenfassende Betrachtung der Evaluierungsergebnisse präsentiert (Tabelle 20).
Evaluationskriterien Ruby on Rails Django Grails
(K1) Funktionale Kriterien
Datenbank und Modelle 1,90 2,50 1,90
Controller 2,60 2,60 2,60
URLRouting 3,00 1,00 3,00
Templates 2,70 2,00 2,30
DatenVerwaltung 2,30 1,80 2,30
BenutzerVerwaltung 2,40 2,00 2,60
KategorieBewertung 2,48 1,98 2,45
Wichtungsfaktor 0,30 0,30 0,30
Gewichtetes Ergebnis 0,74 0,60 0,74
(K2) Dokumentation und ProjektCommunity
Dokumentation 1,00 1,50 2,50
ProjektCommunity 1,00 1,50 4,00
KategorieBewertung 1,00 1,50 3,25
Wichtungsfaktor 0,30 0,30 0,30
Gewichtetes Ergebnis 0,30 0,45 0,98
(K3) Support
Installation 1,50 1,25 2,00
Entwicklungsprozess 2,20 2,20 2,60
AjaxUnterstützung 1,00 1,80 1,50
PluginSupport 1,00 3,00 1,50
Deployment und Webhosting 2,00 2,80 3,50
KategorieBewertung 1,54 2,21 2,22
Wichtungsfaktor 0,20 0,20 0,20
Gewichtetes Ergebnis 0,30 0,44 0,44
100
7 Evaluierung
Evaluationskriterien Ruby on Rails Django Grails
(K4) Entwicklungseffizienz
Implementierungszeit 2,00 2,00 2,00
Codeeffizienz 2,50 2,00 2,70
KategorieBewertung 2,25 2,00 2,35
Wichtungsfaktor 0,10 0,10 0,10
Gewichtetes Ergebnis 0,23 0,20 0,24
(K5) Sonstige Kriterien
Programmiersprache 1,80 1,40 2,40
JobPerspektiven 2,30 3,50 3,30
Security 2,60 3,00 3,00
KategorieBewertung 2,23 2,63 2,90
Wichtungsfaktor 0,10 0,10 0,10
Gewichtetes Ergebnis 0,22 0,26 0,29
Gesamtergebnis: 1,80 2,00 2,70
Tabelle 20: Übersichtstabelle
Das Gesamtergebnis der Evaluierung zeigt, dass das RailsFramework ein deutlicher Gewinner ist. Sein Vorsprung vor Django ist aber sehr gering. In der Kategorie „Funktionale Kriterien“ hat Django allerdings einen Vorsprung durch sein hervorragendes URLRouting und TemplateSystem erworben. In der Kategorie „Dokumentation und ProjektCommunity“ ist Rails der klare Sieger, da seine ProjektCommunity besonders aktiv und stark ist. In der SupportKategorie gewinnt wieder Rails durch perfekten PluginSupport und AjaxUnterstützung. In der EntwicklungseffizienzKategorie haben WebFrameworks nicht so große Unterschiede gezeigt. In der letzten Kategorie „Sonstige Kriterien“ hat Rails die Vorteile gegenüber den anderen WebFrameworks durch bessere JobPerspektiven.
Nach dieser Evaluierung kann man sagen, dass Rails das beliebteste WebFramework seiner Art ist. Dies bedeutet mehr Plugins, Ressourcen (Werkzeuge, Dokumentation, usw.), Arbeitsplätze und HostingServices. Im Vergleich zu beiden anderen WebFrameworks hat es eine hervorragende AjaxUnterstützung und einen umfangreichen PluginSupport. Die Anzahl und die Qualität der RailsPlugins ist beeindruckend. Frühere Versionen von Rails enthielten auch wie Grails eine PaginateFunktion in seiner KernDistribution. Diese wurde ab Rails 2 als Plugin realisiert, was ein wenig enttäuschend ist. Eine sehr nützliche Funktionalität von Rails, die die anderen WebFrameworks noch nicht besitzen, ist die Migration, die die Arbeit mit DatenbankVersionen sehr erleichtert.
101
7 Evaluierung
Die Ergebnisse der Bewertung von Rails und Django unterscheiden sich nicht sehr groß. Aber der erste Eindruck ist, dass Django komplizierter ist und mehr Lernaufwand erfordert als Rails oder Grails. Zum Beispiel vermisst man an vielen Stellen die ConventionoverConfigurationEinstellung von Rails und Grails. Es wurde außerdem keine gute IDE für Django gefunden. Ein großer Gewinn für Django ist sein „loses“ KopplungsPrinzip, in dem jede Komponente des WebFrameworks versucht von den anderen unabhängig zu bleiben. Während alle Komponenten zusammenarbeiten, sind sie nicht voneinander abhängig. Dadurch ist es in den meisten Fällen möglich, Komponenten, wenn gewünscht oder erforderlich, durch Alternativen zu ersetzen.
Viele Stärken von Django liegen an Python. Python ist syntaktisch eine sehr einfache, flexible und reife Sprache. Sie hat viele Module und Bibliotheken, die von Django genutzt werden können. Im Vergleich mit beiden anderen Sprachen wird Python nicht nur für WebAnwendungen genutzt. Außerdem ist Python für die meisten gängigen Betriebssysteme frei erhältlich. Django hat ansprechende und informative DebugMeldungen für die Fehlersuche. Allerdings muss die Fehlerseite während der Produktion deaktiviert werden, da sie viele sensible Informationen über die WebAnwendung enthält.
Auf den ersten Blick sind Rails und Grails sehr ähnlich. Doch bei genauer Betrachtung erkennt man die Unterschiede. Ein großer Vorteil von Grails ist, dass es sich besser für Unternehmen eignet als die beiden anderen WebFrameworks. Es gibt einige Gründe dafür. Grails ist auf integrierten JavaTechnologien wie Spring, Hibernate oder SiteMesh aufgebaut, die eine große Anzahl von Unternehmen nutzen. Diese sind gut etablierte Technologien, die vielen JavaEntwicklern bereits vertraut sind. Grails wurde entworfen, um reibungslos mit Java zu integrieren. Die Integration mit bestehenden JavaTools ist die Stärke von Grails. Man kann die Teile der Anwendung in Java oder in JSPs schreiben. Der Kern von Grails wurde überwiegend in Java entwickelt und ist dadurch robust, performant und skalierbar.
Obwohl es noch nicht so bekannt wie Rails ist, hat Grails schon jetzt eine gewisse PluginAuswahl und relativ aktive Community. Außerdem unterstützen sehr viele IDEs die Arbeit mit Groovy bzw. Grails. Die GrailsAnwendungen sind aber sehr teuer zu hosten. Es bleiben nur virtuelle oder dedizierte Server als eine Alternative. Der Mangel an LowCostWebhostingOptionen für Grails bedeutet, dass Grails am besten für Unternehmen geeignet ist, die sich einen eigenen Server leisten können. Der unreife Debugger ist ein Problem in Grails. Außerdem erfordert Grails in der Entwicklungsphase immer einen Neustart der Webserver um CodeÄnderungen zu sehen. Der GrailsWebserver startet nicht besonders schnell, es kann manchmal bis 20 Sekunden dauern. Grails ist außerdem am wenigsten populär unter den drei verglichenen WebFrameworks.
102
7 Evaluierung
Eindeutig sind alle drei WebFrameworks hervorragende Produkte und bieten eine verbesserte Produktivität und höhere Qualität bei der Entwicklung von WebAnwendungen. Zusammenfassend kann man sagen, dass die Wahl des WebFrameworks die alleinige Entscheidung des Entwicklers ist.
Ein entscheidender Faktor für die Auswahl des WebFrameworks kann die Programmiersprache sein. Beherrscht man bereits eine Programmiersprache und will dabei bleiben, fällt die Auswahl sehr leicht. Besitzt man umfangreiche Programmierkenntnisse in Python, so steht die ganze Reihe der PythonFrameworks wie Django, TurboGears, Pylons für die Entwicklung von WebAnwendungen zur Verfügung. Ist das Erlernen notwendig, benötigt man eine entsprechende Einarbeitungszeit, um die Syntax und Funktionen der Programmiersprache zu verstehen.
103
8 Zusammenfassung
8 Zusammenfassung
Durch komplexer werdende WebAnwendungen ist es notwendig, sich Gedanken über die Wiederverwendbarkeit, Veränderbarkeit, Erweiterbarkeit und der Vereinfachung der Entwicklung zu machen. Ein Lösungsansatz des Problems bietet die agile Softwareentwicklung. Daher wird der agile Ansatz in Betracht gezogen. Die vorliegende Diplomarbeit beschäftigt sich mit der Analyse und dem Vergleich von WebFrameworks im Bereich der agilen Webentwicklung anhand einer Beispielanwendung. Ziel dieser Arbeit ist die Feststellung, welches WebFramework sich am besten für die agile WebEntwicklung eignet.
Nach einer Einführung in die klassischen und die agilen Methoden der Softwareentwicklung und die dahinter stehende Philosophie, erfolgte ein Überblick über die drei ausgewählten WebFrameworks. Für die Analyse wurden die WebFrameworks Ruby on Rails, Django und Grails ausgewählt und vorgestellt. Die umfassende Einarbeitung in die Technologien der drei WebFrameworks ist erforderlich, da die Umsetzung einer Beispielanwendung in jedem Framework erfolgt.
Für einen Vergleich sind Evaluierungskriterien festgelegt. Um einige Kriterien zu überprüfen wurde eine praxisnahe Beispielanwendung zur Verwaltung von Studentenarbeiten entworfen und realisiert. Diese Kriterien dienen gleichzeitig als Anforderungsprofil für die Beispielanwendung. Nach Feststellung aller Anforderungen wurde die Anwendung in den drei WebFrameworks implementiert. Jede Beispielanwendung soll die Verwaltung, die Darstellung von Studenten und die dazugehörigen Studentenarbeiten ermöglichen. Die Realisierung erfolgte auf einem UbuntuLinuxSystem, Version 8.10. Alle drei Beispielanwendungen wurden erfolgreich umgesetzt. Die Vor und Nachteile der Frameworks konnte bei Erstellung der Anwendungen verifiziert werden.
Abschließend werden die ausgesuchten WebFrameworks anhand der definierten Kriterien bewertet und diskutiert. Daraus ist zu erkennen, dass kein perfektes Werkzeug vorhanden ist, jedoch weist Ruby on Rails in diesem Vergleich das beste Ergebnis auf, dicht gefolgt von Django und Grails.
Die erarbeiteten Lösungen bilden eine Grundlage für zukünftige Arbeiten und weiterführende Untersuchungen im Bereich der agilen Webentwicklung.
104
Literaturverzeichnis
Literaturverzeichnis
Printmedien
[AgKomp09] Hruschka, Peter; Rupp, Chris; Starke, Gernot: Agility kompakt.Heidelberg: Spektrum Akademischer Verlag, 2009
[AgThomas] Thomas, Dave; Heinemeier Hansson, David: Agile Webentwicklung mit Rails. München: Carl Hanser Verlag, 2006
[BegROR06] Hellsten ,Christian; Laine, Jarkko: Beginning Ruby on Rails ECommerce.Apress, 2006
[BleekWolf08] Bleek, WolfGideon; Wolf, Henning: Agile Softwareentwicklung: Werte, Konzepte, Methoden. Heidelberg: Dpunkt.Verlag GmbH, 2008
[DefGrails09] Rocher, Graeme, Brown, Jeff: The Definitive Guide to Grails.Apress, 2009
[DjGuide09] Holovaty, Adrian; KaplanMoss, Jacob: The Definitive Guide to Django.Apress, 2009
[GrAction09] Smith, Glen; Ledbrook, Peter: Grails in Action.Manning Publications Co., 2009
[GroovyGrails09] Bashar AbdulJawad: Groovy and Grails Recipes. Apress, 2009
[GrWebApp09] Dickinson, Jon: Grails 1.1 Web Application Development.Packt Publishing, 2009
[JavaMag09] Scheele, MarcOliver: Blogentwicklung in 30 Minuten mit Grails.Java Magazin 4,5,6, 2009
[Komp08] Walter, Thomas: Kompedium der WebProgrammierung.SpringerVerlag Berlin:Heidelberg, 2008
[MarRad06] Marinschek, Martin; Radinger, Wolfgang: Ruby on Rails. Einstieg in die effiziente Webentwicklung. Dpunkt.Verlag GmbH, 2006
105
Literaturverzeichnis
[MunzSoergel07] Munz, Sebastian; Soergel, Julia: Agile Produktenentwicklung im Web 2.0.Boizenburg: Verlag Werner Hülsbusch, 2007
[PractDj09] Bennett, James: Practical Django Projects. Apress, 2009
[PragProg03] Hunt, Andrew; Thomas, David: Der Pragmatische Programmierer.München: Carl Hanser Verlag, 2003
[ProfPyFr07] Moore, Dana; Budd, Raymond; Wright, William: Professional Python Frameworks: Web 2.0 Programming with Django and TurboGearsTM.Wiley Publishing, Inc., 2007
[RailsC07] Orsini, Rob: Rails Cookbook. O’Reilly Verlag, 2007
[RapWeb07] Wirdemann, Ralf; Baustert, Thomas: Rapid Web Development mit Ruby on Rails. München: Carl Hanser Verlag, 2007
[Rupp09] Rupp, Chris: RequirementsEngineering und Management, Professionelle, iterative Anforderungsanalyse für die Praxis.München: Hanser Verlag; 2009
[Stracke08] Stracke,Bettina: Web 2.0 mit Ryby on Rails.Unterhaching: Software & Support Verlag GmbH, 2008
[WebEng] Dumke, Reiner; Lother, Mathias: Web Engineering.München: Peason Studium, 2003
Quellen im Internet
[AgileAlliance] The Agile AllianceURL: http://www.agilealliance.org/Stand: 23.11.2009
[AgileManifesto] Manifesto for Agile Software DevelopmentURL: http://agilemanifesto.org/Stand: 12.12.2009
[AgileModelling] Effective Practices for Modeling and DocumentationURL: http://www.agilemodeling.com/Stand: 28.11.2009
106
Literaturverzeichnis
[AgileWorks] Agile Works in PracticeURL: http://www.ddj.com/architect/191800169Stand: 04.01.2009
[AgPr] The Seven Core Practices of Agile WorkURL: http://www.agileadvice.com/archives/2006/09/practices_of_ag.htmlStand: 25.12.2009
[AgPrakt] The Big List of Agile PracticesURL: http://www.noop.nl/2009/04/thebiglistofagilepractices.htmlStand: 05.12.2009
[AiA] Agile in Action, Iterative and incremental developmentAutor: Simon BakerURL: http://www.thinkbox.co.uk/blog/2005/07/iterativeandincrementaldevelopment.htmlStand: 16.11.2009
[BetterWebApp] Better Web App DevelopmentURL: http://oodt.jpl.nasa.gov/betterwebapp.movStand: 12.11.2009
[DjAjax] Django und AjaxURL: http://www.python.jp/Zope/workshop/200612/files/workshop.htmlStand: 02.02.2010
[DjB] The Django BookURL: http://djangobook.com/en/2.0/Stand: 14.12.2009
[DjRes] DjangoResourcesURL: http://code.djangoproject.com/wiki/DjangoResourcesStand: 12.02.2010
[DjWH] DjangoWebhostingURL: http://code.djangoproject.com/wiki/DjangoFriendlyWebHostsStand: 01.02.2010
[DRY] Dont Repeat YourselfURL: http://c2.com/cgi/wiki?DontRepeatYourselfStand: 06.01.2010
107
Literaturverzeichnis
[ExAgManifesto] Examining the Agile ManifestoURL: http://www.ambysoft.com/essays/agileManifesto.htmlStand: 17.11.2009
[ExPr] Extreme ProgrammingURL: http://www.extremeprogramming.org/Stand: 25.11.2009
[EvWDF] Evaluating Web Development Frameworks: Rails and DjangoURL: http://www.vaporbase.com/railsdjangoStand: 11.02.2010
[GetStartGr] Getting Started with GrailsURL: http://www.infoq.com/minibooks/grailsgettingstartedStand: 0202.2010
[GrDoc] The Grails Framework Reference DocumentationURL: http://grails.org/doc/1.0.x/Stand: 10.02.2010
[GrHost] GrailsHostingURL: http://grails.org/HostingStand: 01.02.2010
[GrPlugins] Grails PluginsURL: http://www.grails.org/plugin/category/allStand: 12.02.2010
[Highsmith] What Is Agile Software Development?Autor: Highsmith Jim, Consortium CutterURL: http://www.stsc.hill.af.mil/crosstalk/2002/10/highsmith.htmlStand: 16.12.2009
[IID] Iterative and incremental developmentURL: http://searchsoftwarequality.techtarget.com/news/article/0,289142 ,sid92_gci1284193,00.htmlStand: 10.01.2010
[Infforum] Informatik ForumURL: http://www.infforum.de/Stand: 15.01.2010
108
Literaturverzeichnis
[PHPFr] Discussing PHP Frameworks: What, When, Why and Which?Author: Joel ReyesURL: http://www.noupe.com/php/discussingphpframeworks. htmlStand: 03.01.2010
[PHPFr2] PHP frameworksURL: http://www.ibm.com/developerworks/library/osphp fwk1/index.html?S_TACT=105AGX44&S_CMP=EDUStand: 03.01.2010
[PHPFr3] Notes on Choosing a PHP Framework: A Comparison of CakePHP and the Zend FrameworkURL: http://2tbsp.com/node/87Stand: 03.01.2010
[PyWebFr] WebFrameworks mit PythonAutor: Hempel SebastianURL: http://www.fhwedel.de/~si/seminare/ws06/Ausarbeitung/09.Python/python0.htmStand: 16.01.2010
[PyWebFr2] Web Frameworks for PythonURL: http://wiki.python.org/moin/WebFrameworksStand: 16.01.2010
[Rails2] Ruby on Rails 2Autor: Hussein Morsy, Tanja OttoURL: http://openbook.galileocomputing.de/ruby_on_rails/index.htmStand: 09.02.2010
[RailsAPI] Rails APIURL: http://api.rubyonrails.org/Stand: 11.02.2010
[RailsPlug] Ruby on Rails PluginsURL: http://wiki.rubyonrails.org/de/gettingstarted/railspluginStand: 02.02.2010
[RailsPlug2] Ruby on Rails PluninsURL: http://www.agilewebdevelopment.com/pluginsStand: 12.02.2010
109
Literaturverzeichnis
[Ruby] RubyURL: http://www.rubylang.org/deStand: 14.12.2009
[ScrAll] Scrum AllianceURL: http://www.scrumalliance.org/articles/Stand: 17.01.2010
[ScrumMaster] Scrum MasterURL: www.scrummaster.deStand: 17.01.2010
[WebFrLeist] Der Leistungsfähigkeitstest der 6 führenden FrameworksURL:http://www.alrond.com/de/2007/jan/25/testresultatenframeworksnachleistungsbestimmungStand: 03.01.2010
[Westphal] Autor: Frank WestphalURL: http://www.frankwestphal.de/Stand: 14.01.2010
[Wiki] Wikipedia, Die freie EnzyklopädieURL: http://de.wikipedia.org/wikiStand: 05.01.2009
[WikiWAF09] Wikipedia: Web Application FrameworkPython URL: http://en.wikipedia.org/wiki/Web_application_framework Stand: 28.11.2009
[WikiFr09] Wikipedia: FrameworkURL: http://de.wikipedia.org/wiki/FrameworkStand: 15.12.2009
110
Anhang A Screenshots
Anhang A Screenshots
GrailsBeispielanwendung „Verwaltung von Studentenarbeiten“Die Anmeldung
Die Startseite
111
Anhang A Screenshots
Die Eingaben zu einem Studenten
Suchfunktion
112
Anhang A Screenshots
Neuen Studenten anlegen
113
Anhang A Screenshots
Neue Studentenarbeit anlegen
114
Anhang A Screenshots
Studentenangaben ändern
Studentenarbeit ändern
115
Anhang A Screenshots
Benutzerliste
Neuen Benutzer anlegen
116
Anhang A Screenshots
Benutzergruppen
Requestmap
117
Anhang B Installation
Anhang B Installation
B.1 Die Ruby on RailsInstallation
1. Ruby wird mit den meisten neueren LinuxDistributionen mitgeliefert, aber man sollte sicherstellen, dass das System eine mit Rails kompatible Version besitzt. Die RubyVersion überprüft man wie folgt:
Ist im System kein Ruby installiert, kann man entweder den Paketmanager der Distribution nutzen oder den Quellcode unter http://www.rubylang.org/de/downloads/ herunterladen. Das Archiv wird an einem geeigneten Ort wie /usr/local/src entpackt, kompiliert und dann installiert:
2. Im nächsten Schritt erfolgt die Installation von RubyGems. RubyGems ist ein Paketverwaltungssystem für Rails und muss speziell installiert werden. Die aktuelle Version muss von der offiziellen Webseite von Ruby heruntergeladen, entpackt und installiert werden.
3. Anschließend wird Rails mit Hilfe von RubyGems installiert:
4. Es ist noch eine Datenbank notwendig. In diesem Fall wird eine MySQLDatenbank benutzt:
5. Eine RailsAnwendung benötigt auch einen Webserver. Für die Entwicklung wird ein WEBrickServer verwendet, der mit Rails mitgeliefert wird. Dieser Server ist kom
118
$ ruby -v ruby 1.8.7 (2008-08-11 patchlevel 72) [x86_64-linux]
$ sudo gem install rails
$ sudo apt-get install mysql-server mysql-client libmysql-ruby libmysqlclient-dev $ sudo gem install mysql
$ tar xzvf rubygems-1.3.1.tgz $ cd rubygems-1.3.1 $ sudo ruby setup
1 /usr/local/src$ tar xzvf ruby-1.8.7.tgz 2 $ cd /usr/local/src/ruby-1.8.7 3 ./configure 4 make 5 sudo make install
Anhang B Installation
plett in Ruby geschrieben und ermöglicht die schnelle und einfache Entwicklung von Anwendungen. Für die Produktion eignet sich der WEBrickServer allerdings nicht, da er zu langsam ist und zu viele Ressourcen verbraucht. In der Produktionsumgebung werden am meisten Apache oder Lighttpd mit FastCGI benutzt.
6. Als weitere Komponente kann noch eine Benutzeroberfläche (IDE) installiert werden. Wenn keine IDE zur Verfügung steht, kann der Quellcode in jedem beliebigen Editor bearbeitet werden. Für die Entwicklung mit Ruby on Rails wurde die NetBeans 6.5 IDE gewählt. NetBeans ist eine Entwicklungsumgebung, die die Arbeit mit der RailsAnwendung erleichtert und beschleunigt. Die aktuelle Version von NetBEans ist auf der offiziellen Webseite zu finden.1
B.2 Die DjangoInstallation
1. Da Django zu 100% in PythonCode geschrieben ist, muss zuerst Python auf dem Computer installiert werden. In der LinuxDistribution ist Python meistens schon standardmäßig installiert. Um zu überprüfen, ob Python installiert ist, kann man im Terminal einfach eingeben:
Ist Python nicht installiert, kann die neuste Version von der Webseite http://python.org/download/ heruntergeladen und installiert werden.
2. Da es sich um eine datenbasierte Anwendung handelt, muss noch die DatenbankEngine installiert werden. Die SQLiteDatenbank verdient dabei besondere Aufmerksamkeit als ein Entwicklungstool für Django, da es sehr einfach ist und keine ServerEinrichtung oder Konfiguration braucht. Die PostgreSQLDatenbank ist jedoch die "empfohlene" Datenbank für die Verwendung mit Django, deshalb wird in dem Projekt auf PostgreSQL gesetzt. Für die Administration von PostgreSQL kann ein pgadmin3 Administrationswerkzeug benutzt werden.
3. Viele Entwickler bieten zur Zeit die Möglichkeit, ihre Software über Subversion (SVN) zu nutzen. Die Software wird dann via SVN heruntergeladen und für das Kompilieren abgelegt. Vorteil dabei ist, dass man ganz einfach den einmal heruntergeladenen Quellcode über SVN aktualisieren kann, um dann eine neue Version der Software zu kompilieren und zu installieren. Da Django immer noch in der Entwick
1 http://www.netbeans.org/
119
~$ python -V Python 2.5.2
Anhang B Installation
lung ist, ist es sehr ratsam einen SVNClient zu installieren, damit Django sehr leicht regelmäßig aktualisiert werden kann.
4. Installation und Konfiguration von postgresql8.3, einem Treiber für die PostgreSQLDatenbank, pgadmin3 und subversion erfolgt im Terminal:
5. Um Django über SVN zu nutzen wird im Homeverzeichnis ein Ordner namens web erstellt, die Quellcode von Django werden heruntergeladen und in ein Verzeichnis django_src abgelegt:
6. Da Python von Django nicht automatisch erkannt wurde, muss ein symbolischer Link zum sitepackagesVerzeichnis erzeugt werden:
7. Die Django admin.pyDatei muss noch in /usr/local/bin kopiert werden, so dass man mit diesem Werkzeug direkt im Terminal arbeiten kann:
8. Es werden im webVerzeichnis drei weitere Unterverzeichnisse erstellt, wo man DjangoProjekte, Templates und Media speichern kann:
9. Der Projektordner muss noch in die PYTHONPATHVariable hinzugefügt werden:
10. Um Django auf einem Produktionsserver nutzen zu können, muss noch extra ein ApacheServer mit dem mod_python oder mod_wsgiModul installiert werden. Das Modul bettet Python in Apache ein und lädt PythonCode in den Speicher, wenn der Server gestartet wird. Django benötigt Apache und mod_python :
120
$ sudo apt-get install subversion python-psycopg2 python-psycopg postgresql-8.3 postgresql-client-8.3
$ mkdir web;cd web $ svn co http://code.djangoproject.com/svn/django/trunk/ django_src
$ sudo ln -s `pwd`/django_src/django /usr/lib/python2.5/site-packages/django
$ sudo cp `pwd`/django_src/django/bin/django-admin.py /usr/local/bin
$ mkdir django_projects; mkdir django_templates; mkdir media
# .bashrc export PYTHONPATH=".:$HOME/web/django_projects"
$ sudo apt-get install apache2 libapache2-mod-python
Anhang B Installation
Um das mod_pythonModul zu konfigurieren, müssen in die Apache Konfigurationsdatei httpd.conf folgende Zeilen hinzugefügt werden:
Das Modul mod_python wird auf Anfragen für die Wurzel der Website konfiguriert. Die Variable sys.path ist eine Liste von Verzeichnissen, wo Djano nach Modulen suchen muss. Standardmäßig übernimmt die Variable den Wert von dem PYTHONPATH. Wenn das nicht der Fall ist, muss in die Variable sys.pyth der Pfad zum Verzeichnis, wo sich alle DjangoProjekte befinden, gespeichert werden. In der Umgebungsvariable DJANGO_SETTINGS_MODULE muss der Pfad zur Konfigurationsdatei des aktuellen Projektes gespeichert werden.
11. Beim Bereitstellen des DjangoProjektes auf mod_python muss man den ApacheServer jedes Mal neu starten, wenn man Änderungen an PythonCode vorgenommen hat. Bei der Benutzung des Entwicklungsservers ist es möglich, um den Server nicht jedes Mal neu starten zu müssen, am Anfang der httpd.confDatei die Zeile MaxRequestsPerChild 1 hinzuzufügen. Dies zwingt Apache, für jeden neuen Request neu zu laden. Diese Zeile muss aber nicht auf einem Produktionsserver genutzt werden.
12. Um die DjangoInstallation zu testen, wird der PythonInterpreter einfach im Terminal gestartet und das DjangoModul importiert. Wenn die Installation korrekt ist, wird die DjangoVersion erscheinen.
B.3 Die GrailsInstallation
1. Für die Implementierung der Beispielanwendung mit Grails wurde die Version 1.1 verwendet. Voraussetzung für die Installation von Grails ist die JDKInstallation. Dafür muss einfach im Synaptic Paket Manager das Paket sunjava6jdk ausgewählt und mit abhängigen Paketen installiert werden.
121
1 <location "/"> 2 SetHandler python-program 3 PythonHandler django.core.handlers.modpython 4 PythonPath "['/home/helga/django_projects'] + sys.path" 5 SetEnv DJANGO_SETTINGS_MODULE studentworkdj.settings 6 </location>
~$ python . . . >>> import django >>> django.VERSION (1, 1, 0, 'alpha', 1)
Anhang B Installation
2. Das letzte GrailsRelease kann von der GrailsWebseite heruntergeladen und im Homeverzeichnis entpackt werden.2
3. Als nächstes müssen noch die Umgebungsvariablen in der bashrcDatei gesetzt werden. JAVA_HOME wird auf die JDKInstallation und GRAILS_HOME auf den entpackten Soursecode von Grails gesetzt. Als letztes wird GRAILS_HOME in die PATHVariable für das Homeverzeichnis hinzugefügt:
4. Die Installation ist erfolgreich, wenn sich der grailsBefehl in einer Konsole aufrufen lässt:
5. Für die Entwicklung einer Beispielanwendung wurde der Editor jEdit benutzt, da er Syntaxhervorhebung für Groovy bietet. GrailsBefehle werden in der Konsole ausgeführt. Für anspruchsvollere GrailsAnwendungen kann eine Entwicklungsumgebung (IDE) die Arbeit wesentlich vereinfachen. Die beste GrailsUnterstützung haben zurzeit IntelliJ IDEA, NetBeans und Eclipse. Als Datenbank wird eine MySQLDatenbank benutzt, da diese eine perfekt abgestimmte Umgebung bietet, leicht zu installieren ist und über phpMyAdmin sehr gut administriert werden kann.
2 http://www.grails.org/
122
export JAVA_HOME=/usr/lib/jvm/java-6-sun export GRAILS_HOME=/home/helga/grails-1.1 export PATH=$PATH:$GRAILS_HOME/bin
$ grails Welcome to Grails 1.1 - http://grails.org/ Licensed under Apache Standard License 2.0 Grails home is set to: /home/helga/grails-1.1
Anhang C Einstellungen des Projektes
Anhang C Einstellungen des Projektes
C.1.1 Einstellungen des DjangoProjektes
1. Damit Django die neu erstellte Applikation nutzen kann, muss sie in die Konfigurationsdatei unter INSTALLED_APPS hinzugefügt werden. Unter diesem Bereich wird auch das AdminInterface definiert:
2. Als Nächstes werden die Datenbankkonfigurationen als auch Zeit und Sprachparameter des Projektes eingestellt:
3. Sehr wichtig ist es, den Pfad zu definieren, unter dem Django nach Templates suchen soll. Am einfachsten erstellt man einen Ordner namens templates in einem Projektverzeichnis und lässt mit os.path den absoluten Pfad zum Projektverzeichnis dynamisch generieren:
4. Django muss noch mitgeteilt werden, wo sich Bilder, CSS und JavaScriptDateien befinden. Der Pfad zu diesen Dateien wird mit dem MEDIA_ROOTParameter definiert. Unter diesem Parameter wird ein absoluter Pfad zu dem Verzeichnis gespeichert, das die Medien für das Projekt enthält. Der Pfad zu den Medien für das AdminInterface wird unter Parameter ADMIN_MEDIA_PREFIX gespeichert. Da das AdminInterface im Projekt ein selbst definiertes Layout nutzt, wird der Parameter ADMIN_MEDIA_PREFIX auf den gleichen Pfad wie MEDIA_ROOT gesetzt:
123
1 INSTALLED_APPS = ( 2 'studentworkdj.students', 3 'django.contrib.admin', 4 )
1 DATABASE_ENGINE = 'postgresql' 2 DATABASE_NAME = 'django_development' 3 DATABASE_USER = 'helga' 4 DATABASE_PASSWORD = 'helga' 5 DATABASE_HOST = '' 6 DATABASE_PORT = '' 7 TIME_ZONE = 'Europe/Berlin' 8 LANGUAGE_CODE = 'de-DE'
1 import os 2 PROJECT_ROOT = os.path.abspath(os.path.dirname(__file__)) 3 TEMPLATE_DIRS = ( 4 os.path.join(PROJECT_DIR, 'templates'), 5 )
1 MEDIA_ROOT ='/home/helga/web/django_projects/studentworkdj/media' 2 ADMIN_MEDIA_PREFIX='/home/helga/web/django_projects/studentworkdj/media/'
Anhang C Einstellungen des Projektes
5. Jetzt muss noch im Projektverzeichnis ein Ordner namens media mit drei weiteren Unterverzeichnissen css, jc und img angelegt werden, wo man die entsprechenden Dateien speichern kann.
6. Es muss noch ein Problem gelöst werden. Django nutzt keine statischen MedienDateien, wie Bilder, Stylesheets oder Videost. Es überlässt diese Aufgabe dem Webserver, je nachdem, welcher Webserver benutzt wird. Deshalb braucht Django statische Dateien zur Unterstützung bei der Entwicklung. Man kann die django.views.static.serveMethode nutzen. Folgende Zeilen müssen zur urls.py Datei hinzugefügt werden:
Mehr Informationen zur serveMethode sind in der Dokumentation nachzulesen.1
7. Wenn das AdminInterface in der Datei settings.py schon definiert wurde, muss noch in der urls.pyDatei die URL zur URLKonfiguration des Projektes hinzugefügt werden:
C.1.2 URLKonfiguration des DjangoProjektes
1. In dem Projekt wurden zwei urls.pyDateien definiert: eine in dem Hauptverzeichnis des Projektes und die zweite Datei in dem Applikationsverzeichnis students. Die Datei urls.py in dem Hauptverzeichnis hat folgende Struktur:
1 http://docs.djangoproject.com/en/dev/howto/staticfiles/
124
1 from django.conf import settings 2 (r'^media/(?P<path>.*)$', 'django.views.static.serve', 3 'document_root': settings.MEDIA_ROOT } ),
1 from django.contrib import admin 2 admin.autodiscover() 3 urlpatterns = patterns('', 4 (r'^admin/', include(admin.site.urls)), 5 )
1 from django.conf.urls.defaults import * 2 from django.contrib import admin 3 admin.autodiscover() 4 5 urlpatterns = patterns('', 6 (r'^admin/', include(admin.site.urls)), 7 ( r'^students/', include( 'students.urls' ) ), 8 )
Anhang C Einstellungen des Projektes
2. In der ersten Zeile werden alle Objekte aus dem Modul django.conf.urls.defaults importiert, einschließlich der Funktion patterns. Beide weiteren Zeilen importieren das AdminInterface. Als nächstes wird die URLAdresse für das AdminInterface definiert. Anschließend, in der Zeile sieben, wird die URLKonfiguration für die Applikation students als eine separate Datei importiert. Diese Datei heißt auch urls.py und befindet sich im Applikationsverzeichnis students:
3. Diese Datei enthält zwei URLs, die bei dem Aufruf eines Studenten oder einer Studentenarbeit eine Detailansicht zeigen. Der erste Parameter /students taucht nicht mehr auf. Dieser Teil wurde bereits durch die erste Datei realisiert.
4. Der zweite Parameter /student bzw. /studentwork ermöglicht den Aufruf von einen einzelnen Studenten und einer einzelnen Studentenarbeit. Im dritten Parameter wird ein regulärer Ausdruck definiert, der mit den Namen student_id bzw. stwork_id versehen ist. Diese Gruppe wird später dem View als Parameter übergeben und repräsentiert den id des Studenten bzw. der Studentenarbeit.
C.2 Einstellungen des GrailsProjektes
1. In Grails gibt es zwei Möglichkeiten eine Datenbankverbindung zu einer externen Datenbank zu konfigurieren: in der Datei DataSource.groovy und als JNDI Datasource in der Datei resources.xml von Spring.
2. Grails kennt drei Laufzeitumgebungen: development, test und production. Immer, wenn der Befehl grails runapp ausgeführt wird, startet Grails automatisch die Webapplikation mit der DevelopmentKonfiguration, welche aus der Datei DataSource.groovy entnommen wird. Wenn eine andere Konfiguration benötigt wird, muss der Name der Laufzeitumgebung angegeben werden:
3. Die Datei DataSource.groovy befindet sich im grailsapp/confVerzeichnis und beinhaltet die Definitionen für die Datenbankverbindung:
125
$ grails dev run-app // Grails in Entwicklungsumgebung starten $ grails test run-app // Grails in Testumgebung starten $ grails prod run-app // Grails in Produktionsumgebung starten
1 from django.conf.urls.defaults import * 2 from students.views import * 3 4 urlpatterns = patterns('', 5 url(r'^student/(?P<student_id>\d+)/$', readStudent), 6 url(r'^studentwork/(?P<stwork_id>\d+)/$', readStwork), 7 )
Anhang C Einstellungen des Projektes
4. Die Datei wird in zwei Abschnitte geteilt. Im ersten Abschnitt dataSource werden zunächst die für alle Umgebungen gültigen Einstellungen vorgenommen.
5. Im environmentsBereich werden für die einzelnen Umgebungen die Einstellungen überschrieben. Der poolingParameter besagt, ob ein Connection Pool für die Datenbankverbindungen benutzt werden soll. Unter driverClassName steht der JDBC Treiber, der in das Verzeichnis \lib kopiert wird. Der Parameter dbCreate besagt, ob das Datenbankschema mit generiert werden soll. Der Parameter kann drei Werte annehmen:createdrop – Die Datenbank wird bei jedem Testlauf erstellt und wieder entfernt.create – Wenn das Schema nicht schon existiert, wird es erzeugt.update – Das Schema wird nur angepasst. Wird die Datenbank manuell erstellt, muss dieser Wert eingegeben werden.
6. Um die Performance einer GrailsAnwendung zu beschleunigen, kann man ein Second Level Cache von Hibernate in der Datei DataSource.groovy definieren:
7. In der DomainKlasse wird der Cache durch folgende Einstellung aktiviert:
126
1 dataSource { 2 pooled = true 3 driverClassName = "com.mysql.jdbc.Driver" 4 username = "admin" 5 password = "admin" 6 } 7 environments { 8 development { 9 dataSource { 10 dbCreate = "update" 11 url = "jdbc:mysql://localhost/grails_development" 12 } 13 } 14 }
1 hibernate { 2 cache.use_second_level_cache=true 3 cache.use_query_cache=true 4 cache.provider_class='com.opensymphony.oscache.hibernate.OSCacheProvider' 5 }
1 class Student { 2 static mapping = { 3 table 'student' 4 cache true 5 ...
Anhang D DeploymentSupport und Webhosting
Anhang D DeploymentSupport und Webhosting
D.1 Ruby on Rails Webhosting
Hoster Datenbanken Leistungen MonatlicheKosten
MindestVertragslaufzeit
Webhoting:
Railshosting.de1 MySQL Ruby on Rails (alle Versionen), RubyGems, Subversion, Git, CapistranoDeployment, SSLZertifikatesScnittstelle: mod_rails
ab 5,00 € keine
Laubingers domainCAMP2
MySQL(bis 5)
Ruby on Rails (alle Versionen), Subversion, Git, SSLZertifikates, freie Installation eigener Gems. Schnittstelle: mod_railsEinmalige Einrichtungsgebühr: 9,00 €
ab 9,00 € von 3 bis 6 Monaten
RailsHoster3 MySQL Capistrano, MySQL, Ruby on Rails 1.2.x und 2.x, PhpMyAdmin, RMagick, Ruby Gems, Subversion, Git
ab 4,95 € 1 Monat
Domainfactory4 MySQL Ruby on Rails ProDomain konfigurierbar ab 9,95 € 1 Monat
LCube5 MySQL Fehlende Gems, durch Support nachinstalliert ab 4,9 € 1 Monat
fiberhead.com6 MySQL Server auf XEN Basis ab 9,99 € 1 Monat
tibit webhosting7 MySQL(bis 10)
ConfixxPro, Ruby on Rails Einmalige Einrichtungsgebühr: 5,90 €
ab 0,79 € 12 Monate
Virtual Server(VPS):
RailsHoster MySQL,PostgreSQL
Die Umgebung mit eigenem Betriebs und Filesystem und mit vollem rootZugriff. Arbeitsspeicher: bis zu 1 GB. Es ist möglich beliebige Software zu installieren, die für die RailsUmgebung nötig ist. Zu den Paketen kann man auf Wunsch weitere Dienstleistungen wie automatische Backups, Monitoring, InstallationsSupport und Weiteres bestellen.
ab 19,95 € 1 Monat
Dedicated Server:
RailsHoster MySQL Ein schlüsselfertigen Server, der über ein vorinstalliertes Betriebssystem mit eingerichteter Ruby on RailsUmgebung verfügt. Standardmäßig wird die Installation mod_rails/Phusion Passenger oder einem Mogrel Cluster angebotten. Man installiert beliebige Software.Einrichtungsgebühr: 149,00 €
ab 99,00 € 1 Monat
1 http://www.railshosting.de/webhosting2 http://www.domaincamp.de/rubyonrailswebhosting3 http://www.railshoster.de/webhosting4 http://www.df.eu/de/produkte/managedhosting/managedhosting/5 http://www.lcubewebhosting.de6 http://www.fiberhead.de/service7 http://www.tibit.de/
127
Anhang D DeploymentSupport und Webhosting
D.2 Django Webhosting
Hoster Datenbanken Leistungen MonatlicheKosten
MindestVertragslaufzeit
PYROX8 MySQL (bis 5)
Das Basishostingpaket stellt die Grundversorgung dar und kann durch Upgrade erweitert werden. Schnittstelle: mod_wsgi
6,00 €
ADIT Systems9 MySQL(bis 5)
Confixx als AdminPanel, zahlreiche PythonPakete zentral installiert.Schnittstelle: mod_wsgi
2,99 € 6 Monate
DjangoEurope10 MySQL,PostgreSQL
Django Hosting in Europe, OneClick DjangoInstaller, Debian, MySQL, PostgreSQL.Schnittstelle: lighttpd, FastCGI
ab 5,00 € keine
djangohosting.ch11 MySQL, PostgreSQL
Django Hosting in Europe, OneClick DjangoInstaller, MySQL, PostgreSQL. Schnittstelle: lighttpd mit FastCGI
4,00 €für 1 GB
3 Monate
DjangoDomain12 SQLite3, MySQL, PostgreSQL
Schnittstelle: apache mit mod_python ab 5,00 € 1 Monat
D.3 Das Deployment einer GrailsWebanwendung
Hoster Datenbanken Leistungen MonatlicheKosten
MindestVertragslaufzeit
eatj13 MySQL JSP/Servlets, Tomcat, JVM ab 9,85 $ keine
KGB Internet14 MySQL JSP/Servlets, Tomcat, JVM ab 10,00$ keine
Daily Razor15 MySQL JSP/Servlets, Tomcat, JVM ab 4,60 $ 1 Monat
KATTARE16 MySQL JSP/Servlets, Tomcat, JVMBereitstellungsgebühr: ab 15$
ab 19,00 $ keine
HostJava17 MySQL JSP/Servlets, Tomcat, JVM ab 7,99 $ keine
4Java.ca18 MySQL JSP/Servlets, Tomcat, JVM ab 7,74 € 1 Monat
javaprovider19 MySQL JavaProvider Dedicated JVM Hosting Options, Tomcat
ab 9,99 $
8 http://pyrox.eu/webhosting/9 https://www.aditsystems.de/10 https://www.DjangoEurope.com11 http://djangohosting.ch/12 http://www.djangodomain.com/13 http://eatj.com/plans.jsp14 http://www.kgbinternet.com/service.htm15 http://www.dailyrazor.com16 http://www.kattare.com/hostingpricingchart.kvws17 http://www.hostjava.net18 http://www.4java.ca/19 http://javaprovider.net/
128
Anhang E Security
Anhang E Security
E.1 SQLInjection
SQLInjection1 ist eine StandardSchwachstelle der WebAnwendung, bei der die Sicherheitslücken in den SQLAnfragen durch die mangelnde Maskierung oder Überprüfung von Metazeichen in Benutzereingaben entstehen. Es ist wahrscheinlich der gefährlichste und leider auch eine der am häufigsten treffende Schwachstelle in einer WebAnwendung. Diese Sicherheitsanfälligkeit taucht am häufigsten beim Bau der SQLAnfragen "von Hand" auf. Als Beispiel kann eine DjangoFunktion betrachtet werden, die eine Liste der Kontaktinformationen aus einem Suchfeld ausgibt [DjB].
Diese Sicherheitslücke wird oft unterschätzt, hat jedoch große datenschutzrechtliche Auswirkungen. Gibt ein Angreifer „'OR 'a'='a“ in das Suchfeld ein, wird folgende Abfrage generiert:
Weil die user_contactsFunktion ungesicherte SQL erlaubt, wird dadurch jede einzelne Zeile zurückgegeben. Gibt der Angreifer in dem Suchfeld folgendes ein: „'; DELETE FROM user_contacts WHERE' a '=' a“, wird die Anfrage generiert:
Nach dieser Anfrage wird die gesamte Kontaktliste sofort gelöscht.
Obwohl dieses Problem manchmal schwer zu erkennen ist, ist die Lösung sehr einfach: nie den vorgelegten BenutzerDaten vertrauen und immer alles maskieren, was in der SQLAnfrage genutzt wird. Sobald man eigene SQLAbfragen formuliert, muss man darauf achten, dass die Metazeichen maskiert sind.
1 http://de.wikipedia.org/wiki/SQLInjection
129
1 def user_contacts(request): 2 user = request.GET['username'] 3 sql = "SELECT * FROM user_contacts WHERE username = '%s';" % username 4 # execute the SQL here...
SELECT * FROM user_contacts WHERE username = '' OR 'a' = 'a';
1 SELECT * FROM user_contacts WHERE username = ''; 2 DELETE FROM user_contacts WHERE 'a' = 'a';
Anhang E Security
Die obere user_contactFunktion von Django kann man wie folgt umschreiben:
Django maskiert automatisch alle speziellen SQLParameter. Zum Beispiel folgender Befehl:
entspricht der SQLAnfrage, die ungefährlich ist.
Hibernate, die die zugrunde liegende Technologie von GORM ist, maskiert automatisch Daten bei der DatenbankAbfrage. Alle StandardDatenbankAnfragen via GORM DomainObjekten verhindern automatisch SQLInjectionsAngriffe. Es ist allerdings möglich HQLCode zu entwickeln, die unkontrollierte Anfragen erlauben [GrDoc]:
Im RailsFramework ist der Schutz von SQL InjectionsAngriffen schon integriert. Nutzt man die von ActiveRecord zur Verfügung gestellten Methoden ohne conditions, limits oder eigene SQLAbfragen, übernimmt ActiveRecord automatisch die Maskierung aller Metazeichen [Rails2].
130
SELECT * FROM foos WHERE bar = '\' OR 1=1'
foo.get_list(bar__exact="' OR 1=1")
1 //anfällig für SQL-Injections-Angriffe 2 def vulnerable = { 3 def books = Book.find("from Book as b where b.title ='" + params.title + "'") 4 } 5 6 //nicht anfällig für SQL-Injections-Angriffe 7 def safe = { 8 def books = Book.find("from Book as b where b.title =?", [params.title]) 9 }
1 from django.db import connection 2 3 def user_contacts(request): 4 user = request.GET['username'] 5 sql = "SELECT * FROM user_contacts WHERE username = %s" 6 cursor = connection.cursor() 7 cursor.execute(sql, [user])
Anhang E Security
E.2 CrossSiteScriptingInjection
Bei dem CrossSiteScripting (XSS)Angriff2 werden die Benutzereingaben, die an eine WebAnwendung übergeben werden, manipuliert. Dabei wird nicht die WebAnwendung selbst, sondern der Browser eines rechtmäßigen Benutzers angegriffen. Es wird versucht den Browser dazu zu bringen, bestimmte Aktionen im Namen des rechtmäßigen Benutzers auszuführen. Durch Ausnutzung von Sicherheitslücken in der Anwendung kann ein Angreifer unter anderem schädliche Programmcode in eine für den Benutzer normalerweise korrekte Umgebung einbetten. Oder er versucht eine gewisse Kontrolle über die Ausführung der WebAnwendung zu erlangen, die er zu seinen Zwecken ausnutzen will.
Diese Art von Angriff findet in der WebAnwendung statt, wenn die von einem Benutzer eingegebene Information, bevor sie in HTMLCode der Seite hinzugefügt wird, nicht maskiert wird. Dies ermöglicht dem Angreifer einen bestimmte HTMLCode, gewöhnlich <script>, auf die Webseite hinzuzufügen. Als Beispiel kann eine einfache DjangoFunktion dienen [DjB]:
Diese Aktion liest einfach einen Namen aus einem GETParameter und übergibt diesen in die generierte HTML. Also, wenn man folgende URL eingibt:
erscheint als Antwort folgende Zeile:
Wird solche URL eingegeben:
erfolgt die Antwort:
2 http://de.wikipedia.org/wiki/CrossSite_Scripting
131
1 from django.http import HttpResponse 2 def say_hello(request): 3 name = request.GET.get('name', 'world') 4 return HttpResponse('<h1>Hello, %s!</h1>' % name)
<h1>Hello, Jacob!</h1>
<h1>Hello, <i>Jacob</i>!</h1>
http://example.com/hello/?name=Jacob
http://example.com/hello/?name = <i> Jacob </ i>
Anhang E Security
Natürlich bringt es dem Angreifer nichts, wenn er das <i>Tag verwendet. Er kann eine ganze Reihe von HTMLCode nehmen und die Webseite mit beliebigen Inhalten füllen. Diese Art des Angriffs wird verwendet, um Benutzer zu zwingen die persönlichen Informationen, wie zum Beispiel das BankKonto, zu zeigen.
Die Lösung ist einfach: immer jegliche Inhalte, die von einem Benutzer kommen können, maskieren, bevor sie in HTML hinzugefügt werden. Schreibt man das obige Beispiel so um:
und gibt folgende URL ein:
erscheint diese ungefährliche Ausgabe:
Man muss aber immer daran denken, dass es keine automatische Lösung gibt, um die Webseiten von XSSAngriffen zu hundert Prozent zu schützen.
132
1 #views.py 2 from django.shortcuts import render_to_response 3 def say_hello(request): 4 name = request.GET.get('name', 'world') 5 return render_to_response('hello.html', {'name': name}) 6 7 # hello.html 8 <h1>Hello, {{ name }}!</h1>
http://example.com/hello/name = <i> Jacob </ i>
<h1>Hello, <i>Jacob</i>!</h1>
Anhang E Security
E.3 CrossSiteRequestForgery
Bei einem CrossSiteRequestForgery (CSRF)Angriff verändert der Angreifer unberechtigt die Daten einer WebAnwendung. Der Angreifer bedient sich eines Opfers, das ein berechtigter Benutzer der WebAnwendung ist. Aus dem Webbrowser des Opfers wird ohne dessen Wissen und Einverständnis eine entsprechend präparierte HTTPAnfrage an die WebApplikation geschickt. Der CSRFAngriff passiert, wenn eine schädliche Website den Benutzer zu unwissentlichen Laden einer URL von einem Ort, an dem er bereits authentifiziert ist, zwingt. Das kann zum Beispiel über ein manipuliertes imgTag erfolgen, das in einer EMail enthalten ist und statt der URL zur Grafik die präparierte Anfrage des Angreifers enthält.
Das heißt, die Anfrage wird von der WebApplikation so verarbeitet, als wäre sie vom Opfer autorisiert. Statt eines imgTags kann auch JavaScriptCode verwendet werden. Das Risiko kann minimiert werden, indem zur Abfrage von Daten nur die HTTPMethode GET benutzt wird. Alle anderen Aktionen sollten dann per POST, PUT oder DELETE gesendet werden [Rails2].
Der zweite Schritt besteht darin, dass in jedem POSTFormular ein verborgenes Feld hinzugefügt wird, dessen Wert aus der SessionID des Benutzers erzeugt wurde. Findet die Bearbeitung des Formulars auf der Serverseite statt, muss dieses Feld überprüft werden. Besteht der Wert die Prüfung nicht, wird eine Fehlermeldung ausgelöst. Beide WebFrameworks Rails und Django haben die Werkzeuge um die CSRFAngriffe zu verhindern. Ab Rails 2.0 ist das CSRF killerPlugin in Rails integriert. Das Plugin generiert für alle in Rails generierten Formulare einen Security Token, der über ein verstecktes Feld übertragen wird. Das heißt, für alle Formulare, die mit dem ScaffoldGenerator oder der HelperMethode form_for generiert werden, wird automatisch ein Security Token generiert, der über ein verstecktes Feld (authenticity_token) übertragen wird. Django hat ein django.contrib.csrfPaket, das ein einziges middleware.pyModul mit CsrfMiddlewareKlasse enthält, die den Schutz gegen dier CSRFAngriffe implementiert.
133
Anhang E Security
E.4 SessionAngriffe
SessionAngriffe sind keine speziellen Angriffe, sondern eine allgemeine Klasse von Angriffen auf SessionDaten eines Benutzers. Es kann eine Reihe von verschiedenen Formen annehmen:
• Ein maninthemiddleAngriff, wo ein Angreifer die SessionDaten liest, wenn sie durch das Netzwerk (oder WLAN) laufen.
• In einem Session HijackingAngriff nutzt ein Angreifer eine SessionID eines Benutzers, die er vielleicht durch einen maninthemiddleAngriff erhalten hat. Häufig kommen die Angreifer durch Sniffing in unsichere Netzwerke wie z.B. WLANNetzen oder in Internetcafés, an die erforderlichen Daten. Um sich vor Angriffen zu schützen, müssen die Cookies über das HTTPSProtokoll geschickt werden.
• In einem Session FixationAngriff zwingt der Angreifer den Benutzer die Einstellungen der UserSessionID zurückzusetzen. Zum Beispiel erlaubt PHP der SessionID in die URL zu übergeben.Ein Angreifer kann diese ID in die URL stellen. Klickt der Benutzer auf solchen Link, wird es dazu führen, dass diese Session abgeholt wird. SessionFixation wurde in PhishingAngriffe verwendet, um Benutzer zu zwingen, seine persönlichen Daten in einen Account der Angreifer einzugeben.
Es gibt eine Reihe von Grundsätzen, um sich vor diesen Angriffen schützen zu können:• Die SessionInformationen müssen niemals in der URL enthalten sein.• Die Cookies müssen immer über das HTTPSProtokoll geschickt werden.• Daten müssen nicht in Cookies gespeichert werden. Stattdessen wird eine SessionID
in der Datenbank gespeichert. • Die SessionDaten müssen maskiert werden, wenn sie in dem Template gezeigt wer
den.• Meldet der Benutzer erfolgreich ab, muss eine neue Session erzeugt werden. Die Da
ten der alten Session müssen in die neue kopiert werden.• Beim Abmelden eines Benutzers muss seine Session entwertet werden.
134
Anhang G CD
Anhang G CD
Inhalt der beigelegten CD: • Die Diplomarbeit im PDFFormat• Die Quelltexte der Beispielanwendungen mit Ruby on Rails, Django und Grails
135
Selbstständigkeitserklärung
Ich versichere, dass ich die Diplomarbeit selbständig verfasst und keine anderen als die angegebenen Quellen und Hilfsmittel benutzt habe. Die wörtlich oder sinngemäß entnommenen Stellen sind als solche kenntlich gemacht.
Dresden, 08.03.2010
Helga Nickel