Bachelorarbeit

Entwicklung einer Webapplikation zur Unterstützung der Lehr- und Stundenplanung
Zur Erlangung des akademischen Grades eines Bachelor of Science - Informatik-

Fakultät Informatik Referent: Prof. Dr. Oliver Braun Korreferent: Dipl. Math. Gerd Recknagel eingereicht von: Christoph Schmidt Matr.-Nr. 281094 Leitenstraße 8 97795 Schönderling Schmalkalden, den 09.08.2011

Inhaltsverzeichnis
1 Einführung 1.1 Motivation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.2 Zielsetzung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.3 Das SPIRIT-Projekt . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 Grundlagenbetrachtung 2.1 Scala . . . . . . . . . . . . . . . . . . . . . . . . 2.1.1 OOP versus funktionale Programmierung 2.1.2 Besonderheiten . . . . . . . . . . . . . . 2.2 Lift . . . . . . . . . . . . . . . . . . . . . . . . . 2.2.1 Architektur . . . . . . . . . . . . . . . . 2.2.2 Lift Core und Lift Web . . . . . . . . . . 2.2.3 Persistenz . . . . . . . . . . . . . . . . . 2.2.4 Projektstruktur . . . . . . . . . . . . . . 2.2.5 Konfiguration . . . . . . . . . . . . . . . 3 Analyse 3.1 Zielsystem . . . . . . . . . . . . . . 3.2 Benutzeranalyse . . . . . . . . . . . 3.3 Anwendungsfälle . . . . . . . . . . 3.3.1 Lehrplanungsprozess . . . . 3.3.2 Arbeitszeiterfassungsprozess 4 Design 4.1 Drei-Schichten-Architektur 4.2 Vier-Schichten-Architektur 4.3 Softwarekomponenten . . . 4.4 Konkretes Design . . . . . 4.4.1 Datenhaltung . . . 4.4.2 Anwendungskern . 1 1 2 2 4 4 4 5 9 9 11 13 14 15 17 17 17 18 19 20 21 21 21 21 22 22 25 29 29 29 30 31 31 32 33

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

5 Implementierung 5.1 Entwicklungsumgebung und Buildtools 5.1.1 IntelliJ . . . . . . . . . . . . . . 5.1.2 Simple-Build-Tool . . . . . . . . 5.2 Menü und Zugriffskontrolle . . . . . . . 5.2.1 FhS-LDAP-Module . . . . . . . 5.2.2 SiteMap . . . . . . . . . . . . . 5.3 Persistenz und Transformation . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

Christoph Schmidt

II

Inhaltsverzeichnis 5.4

Fachhochschule Schmalkalden SS 2011 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35 36 37 37 40 43 45 47 49

5.5 5.6

Lehrveranstaltungsverwaltung und Planung . . . 5.4.1 Template Method-Muster . . . . . . . . . 5.4.2 Umsetzung des Template Method-Musters 5.4.3 Planungsprozess . . . . . . . . . . . . . . . Arbeitszeitverwaltung . . . . . . . . . . . . . . . . Testfälle . . . . . . . . . . . . . . . . . . . . . . .

6 Fazit und Ausblick Literaturverzeichnis Eidesstattliche Erklärung

Christoph Schmidt

III

1 Einführung
Diese Arbeit beschäftigt sich mit der Implementierung einer Web-Anwendung zur Unterstützung der Lehr- und Stundenplanung an der Fachhochschule Schmalkalden, welche auf Scala 1 und Lift 2 basieren soll. Für das Verständnis der Arbeit werden Kenntnisse in Scala vorausgesetzt.

1.1 Motivation
In den vergangenen Jahren hat sich das Internet stark weiterentwickelt. Vom ursprünglichen Gedanken wissenschaftliche Dokumente auszutauschen, spricht heute kaum noch jemand. Hört man heute Menschen über das Internet sprechen, dreht sich alles um soziale Netzwerke, Blogs, Wikis und Podcasts. Der Erfinder des Internets, Tim Berners-Lee, äußert sich folgendermaßen über seine Erfindung: “The web is more a social creation than a technical one. I designed it for a social effect - to help people work together - and not as a technical toy.” [Gre08] Dabei lässt sich noch ein weiterer Trend beobachten. Anwendungen, die früher auf Desktop-Computern installiert waren, verlagern sich immer mehr in das Internet und bieten eine Möglichkeit interaktiv an Projekten zu arbeiten, wie es vorher nur schwer möglich war. Ein Beispiel hierfür ist der von Google Inc. angebotene Dienst Google Docs. Mit diesem ist es möglich Präsentationen oder Textdokumente zu erstellen, welche von mehren Benutzern gemeinsam bearbeitet werden können. Dabei erinnert das Arbeiten stark an herkömmliche Desktop-Anwendungen. Auch die dafür benötigten Technologien haben sich in den letzten Jahren stark weiterentwickelt. Gerade im Bereich der Programmierung sind weitere Trends erkennbar. Es sind neue Sprachen entstanden, die die Objektorientierung mit Konzepten der funktionalen Programmierung vereinen. Auch das European Research Council 3 erkannte diesen Trend und förderte die Weiterentwicklung der Sprache Scala mit einem Betrag in Höhe von 2,3 Millionen Euro [Ano11]. Im Scala-Umfeld ist das Web-Framework Lift entstanden, welches im Vergleich zu anderen Frameworks seiner Art die meisten der Top 10 Sicherheitslücken, welche von der OWASP 4 herausgegeben wurde, wie Injection 5 oder Cross-Site Scripting 6 von vornherein ausschließt [Pol11a].
1 2

Scala ist eine objekt-funktionale Programmiersprache. Lift ist ein in Scala programmiertes Web-Framework. 3 http://erc.europa.eu/ 4 OWASP steht für Open Web Application Security Project. 5 Injection bezeichnet das Ausnutzen einer Sicherheitslücke in Verbindung mit einer Datenbank. 6 Cross-Site Scripting ist eine Sicherheitslücke bei der es möglich ist schadhaften Quellcode durch Formulareingaben in Webseiten zu platzieren.

Christoph Schmidt

Seite 1 von 49

1. Einführung

Fachhochschule Schmalkalden SS 2011

1.2 Zielsetzung
Wie einführend erwähnt ist das Ziel dieser Arbeit die Entwicklung einer WebAnwendung mit dem Namen PlanningWeb zur Unterstützung der Lehr- und Stundenplanung. Eine der Hauptaufgaben besteht darin, eine gemeinsame Plattform für die Planung des Curriculums und Stundenplanung zu schaffen, um den Arbeitsaufwand zu minimieren. Die für diese Aufgaben bisher eingesetzten Programme liegen als reine DesktopAnwendung vor, welche auf Basis der deklarativen Sprache Prolog implementiert wurden. Allerdings können diese die über die Jahre gewachsenen Anforderungen nicht mehr im vollen Maße erfüllen. Darüber hinaus werden die bislang eingesetzten Programme von neueren Windows-Versionen wie Windows 7 nicht mehr unterstützt, was für die Zukunft mit einer internetfähigen Version vermieden werden soll. Um dies zu erreichen, sollen die Möglichkeiten der Sprache Scala und im speziellen die des Lift-Frameworks untersucht werden. Dazu kommt Scala in der Version 2.8.1 und Lift in der Version 2.3 zum Einsatz. Im Bereich Datenspeicherung ist zu untersuchen, wie eine datenbankunabhänige Speicherung erzielt werden kann, um sich auch hier nicht zu stark an ein Datenbank-Produkt zu binden. Für die Darstellung der einzelnen Dialoge sollen herkömmliche Elemente wie Textfelder, Check-Boxen und Buttons eingesetzt werden. Für die grafische Darstellung wird weitestgehend das Standard-CSS des Frameworks verwendet, da dies nicht Bestandteil der Arbeit ist.

1.3 Das SPIRIT-Projekt
Die hier durchgeführte Arbeit findet ihm Rahmen des SPIRIT-Projekts der Fachhochschule Schmalkalden an der Fakultät Informatik statt. Dieses Projekt beschäftigt sich mit der Neuimplementierung der Stundenplanungstools sowie dazugehöriger Applikationen. Abbildung 1.1: SPIRIT-Projekt

Christoph Schmidt

Seite 2 von 49

1. Einführung

Fachhochschule Schmalkalden SS 2011

Abbildung 1.1 zeigt eine grobe Strukturübersicht der einzelnen Projekte und ihr Zusammenspiel. Das EmployeeWeb wird, genau wie dieses Projekt, mit Scala und Lift realisiert. Es dient dazu Dozenten eine Möglichkeit zu geben, Informationen, die die Studierenden betreffen, in Spirit einzustellen. Diese Informationen werden den Studierenden über das StudWeb zugänglich gemacht, wobei der Datenaustausch der Anwendungen über den zentralen Datenbank-Service realisiert wird. Da sich die Nutzer des EmployeeWeb mit denen des PlanningWebs überschneiden und beide die gleichen Basistechnologien nutzen, ist für die Zukunft geplant beide Applikationen in einer zu vereinen. Weiterführende Informationen zu diesem Projekt sind auf der Projektseite 7 oder auf Github8 zu finden.

7 8

http://pads.fh-schmalkalden.de/spirit.html https://github.com/spirit-fhs

Christoph Schmidt

Seite 3 von 49

2 Grundlagenbetrachtung
In diesem Kapitel wird kurz die Sprache Scala und das Lift-Framework vorgestellt. Zu Beginn wird auf die Entstehungsgeschichte von Scala eingegangen. Im Anschluss wird kurz die objektorientierte Programmierung der funktionalen Programmierung gegenübergestellt um darauf aufbauend die Besonderheiten der Sprache darzustellen. Nachdem Scala ausreichend vorgestellt wurde, wird auf das Lift-Framework eingegangen. Im Zuge dessen wird auch die Architektur des Frameworks untersucht.

2.1 Scala
Der Startschuss für Scala fiel 2001 an der Ècole polytechnique fèdèrale de Lausanne in der Schweiz unter der Leitung von Professor Martin Odersky. 2003 wurde das erste Release veröffentlicht. Anschließend erschien im Jahr 2006 die Version 2.0 und im Jahr 2010 Version 2.8 [Bra10, S. 1]. Derzeit ist Scala in der aktuellen Version 2.9 verfügbar. Vor der Entwicklung von Scala arbeitete Martin Odersky bereits an einer Sprache, die die Objektorientierung mit Konzepten der funktionalen Programmierung vereinen sollte. Es entstand Funnel 1 . Diese Sprache war aus Sicht eines Sprachentwicklers sehr “rein”. Sie besaß lediglich ein paar primitive Spracheigenschaften. Fast alles, einschließlich Klassen, wurde durch Bibliotheken realisiert. Es stellte sich allerdings heraus, das eine Sprache nur dann akzeptiert wird, wenn sie eine große Anzahl an Standard Bibliotheken bereitstellt. Aus den Ideen von Funnel entstand schließlich die Sprache Scala, wobei der Fokus bei ihr auf die Zusammenarbeit mit Standard-Plattformen wie Java gelegt wurde [Ode08].

2.1.1 OOP versus funktionale Programmierung
Der in der Mathematik verwendete Begriff einer Funktion spielt in der funktionalen Programmierung eine zentrale Rolle, da diese auf dem dort verwendeten Begriff basiert. Die Eingabewerte stellen dabei den Definitionsbereich einer Funktion dar. Die Funktion wiederum bildet diese auf Rückgabewerte, welche dem Wertebereich entsprechen, eindeutig ab [PH06, S. 11]. Daraus folgt, dass Funktionen die immer mit dem gleichen Wert aufgerufen werden auch immer das selbe Resultat als Wert zurückgeben. Ein weiterer elementarer Bestandteil von funktionalen Sprachen sind Funktionen höherer Ordnung. Darunter versteht man Funktionen, welche als Eingabeparameter

1

http://lampwww.epfl.ch/funnel/

Christoph Schmidt

Seite 4 von 49

2. Grundlagenbetrachtung

Fachhochschule Schmalkalden SS 2011

selbst wiederum Funktionen erwarten, wodurch letztlich ein Großteil an Produktivität dieses Programmierparadigmas erzielt wird [PH06, S. 23 f.]. In diesem Zusammenhang taucht häufig der Begriff der anonymen Funktionen auf. Diese werden oft als Argumente für Funktionen höherer Ordnung eingesetzt. Sie können deshalb direkt aufgeschrieben werden, ohne ihnen eine Bezeichnung zu geben [PH06, S. 14]. Im Gegensatz zur funktionalen Programmierung steht in der objektorientierten Programmierung der Objektbegriff im Vordergrund. Ein Objekt repräsentiert in diesem Zusammenhang ein eindeutiges Exemplar von Dingen, wie beispielsweise ein Auto. Objekte besitzen Eigenschaften bzw. Attribute sowie ein bestimmtes Verhalten, was durch eine Anzahl an Methoden ausgedrückt wird [Hom02, S. 4]. Eine Klasse wiederum bildet eine Vorlage für ein Objekt und ist somit ein Objekttyp. Die Gemeinsamkeiten einer Menge von Objekten werden daher in Klassen zusammengefasst und spezifiziert. Daraus folgt, dass Objekte als Instanzen einer Klasse bezeichnet werden [Hom02, S. 6]. Durch das Konzept der Kapselung bleiben Implementierungsdetails hinter spezifizierten Schnittstellen verborgen, was dazu führt, dass die Darstellung eines Objekts nur entsprechend seiner Spezifikation genutzt werden kann [Hom02, S. 5].

2.1.2 Besonderheiten
Scala gilt als Hybrid-Sprache, da sie Merkmale der objektorientierten und funktionalen Welt vereint. Scala-Quellcode wird in Java-Bytecode umgewandelt, was es so problemlos ermöglicht Java-Code zu integrieren. Außerdem ist Scala eine rein objektorientierte Programmiersprache, da jeder Wert ein Objekt repräsentiert. Darüber hinaus ist diese Sprache im Vergleich mit anderen modernen Vertretern ihrer Art statisch typisiert, was dazu führt, dass der Typ aller Ausdrücke bereits zur Kompilierzeit überprüft wird und so unerwünschte Typfehler ausschließt [Bra10, S.1 f.]. Knappheit der Sprache Scala-Programme haben die Eigenschaft im Vergleich zu Java eher kurz zu sein. Sie sind meist um den Faktor 10 kürzer als ein vergleichbares Programm in Java. Weniger Zeilen an Quellcode bedeutet aber nicht nur weniger Schreibarbeit sondern fördert auch die Lesbarkeit und Verständlichkeit des Quellcodes. Darüber hinaus bedeuten weniger Zeilen auch potenziell weniger Fehler im Programm selbst. Es gibt einige Faktoren die dazu beitragen die Anzahl an Zeilen des Quellcodes zu verringern. Beispielsweise vermeidet die Syntax von Scala einiges an Standardformulierungen, welche Java-Programme belasten. Semikolons sind optional und können in den meisten Fällen einfach weggelassen werden. Es gibt viele weitere Bereiche, in denen die Scala-Syntax übersichtlicher ist. Bei Betrachtung von Klassendefinitionen mit Konstruktoren fällt dies besonders auf, was die nachfolgenden Beispiele, Listing 2.1 und Listing 2.2 darstellen sollen. Das erste Listing stellt die Definition einer Java-Klasse dar.

Christoph Schmidt

Seite 5 von 49

2. Grundlagenbetrachtung

Fachhochschule Schmalkalden SS 2011

Listing 2.1: Java-Klasse mit Konstruktor class A { private int x ; private String y ; public A ( int x , String y ) { this . x = x ; this . y = y ; } } Im zweiten Listing ist die Definition einer Scala-Klasse zu sehen und wie unschwer zu erkennen ist, ist diese sehr viel kürzer und übersichtlicher. Allerdings besitzt diese Definition exakt die gleiche Funktionalität wie die zuvor dargestellte Klassendefinition. Listing 2.2: Scala-Klasse mit Konstruktor class A ( x: Int , y: String ) Ein weiterer Grund für die Knappheit von Scala ist auf ihre Typinferenz 2 zurückzuführen. Typangaben können teilweise weggelassen werden, was zur Folge hat, dass Programme lesbarer werden. Letztendlich ist aber der wichtigste Punkt um Quellcode kompakt zu halten der Code, der gar nicht erst geschrieben werden muss, da er in Form von Bibliotheken vorliegt. Für diese Zwecke stellt Scala viele Werkzeuge zur Verfügung, um leistungsstarke Bibliotheken zu erzeugen. Viele Aspekte von Bibliotheken können in Traits ausgelagert werden, welche dann flexibel zusammengesetzt werden können. Darüber hinaus können Bibliotheksfunktionen mit Operationen parametrisiert werden, welche es ermöglichen Konstrukte zu definieren, die schlussendlich eigene Kontrollstrukturen darstellen. Diese Konstrukte ermöglichen es Bibliotheken zu definieren, welche zugleich hochrangig als auch flexibel zu nutzen sind [OSV10, S. 13 ff.]. Kompatibilität Wie bereits angesprochen ist Scala kompatibel zu Java 3 . Scala erzeugt JVM-Bytecode, dessen Laufzeitleistung dem von Java Programmen entspricht. Aus Scala heraus können Java Methoden aufgerufen und auf Felder zugegriffen werden, die sich in Java Klassen befinden. Außerdem können Java Interfaces implementiert werden. All das erfordert keine spezielle Syntax. Ein weiterer Grund für die Zusammenarbeitsfähigkeit besteht darin, dass Scala die Java Typen wiederverwendet. Es werden z. B. die von Scala verwendeten Ints als primitive Integer von Java’s ints dargestellt. Außerdem verwendet Scala viele der Java Bibliothekstypen wie den Typen eines String-Literals. Scala verwendet diese Typen jedoch nicht eins zu eins. Sie sind erweitert und in vielen Situationen komfortabler zu nutzen.
2

Durch Typinferenz kann an einigen Stellen auf Typangaben verzichtet werden, da der entsprechende Typ durch Typisierungsregeln hergeleitet werden kann. 3 Es gibt auch eine Scala Variante die auf der .NET Plattform läuft, allerdings wird die JVM Variante derzeit besser unterstützt.

Christoph Schmidt

Seite 6 von 49

2. Grundlagenbetrachtung

Fachhochschule Schmalkalden SS 2011

Scala Quellcode kann auch aus Java heraus aufgerufen werden, was allerdings nicht so einfach möglich ist, da Scala eine reichhaltigere Sprache ist als Java. Deshalb müssen einige modernere Eigenschaften umgewandelt werden bevor sie in Java genutzt werden können [OSV10, S. 12 f.]. Hochsprache Scala ermöglicht es den Abstraktionsgrad zu erhöhen, was dazu führt, dass der Fokus bei der Programmierung stärker auf das Problem selbst gelegt werden kann, um so ein Ziel besser zu erreichen, da zu komplexer Quellcode oft zu einem Aus für ein Software-Projekt führen kann. Dies soll nachfolgendes Beispiel verdeutlichen, welches überprüft ob eine Zeichenkette, die durch die Variable name repräsentiert wird, Großbuchstaben enthält oder nicht. Listing 2.3: Beispiel Java /* Programming in Scala : Second Edition S. 15 */ boolean nameHasUpperCase = false ; for ( int i= 0; i < name . length () ; ++ i ) { if ( Character . isUpperCase ( name . charAt ( i ) ) ) { nameHasUpperCase = true ; break ; } } Listing 2.3 zeigt eine derartige Implementierung in Java wohingegen Listing 2.4 dasselbe in Scala Syntax darstellt. Listing 2.4: Beispiel Scala /* Programming in Scala : Second Edition S. 15 */ val nameHasUpperCase = name . exists (_. isUpper ) Bei diesem Beispiel wird deutlich, dass bei Scala-Code direkt das Problem angegangen werden kann. Es müssen nicht, wie bei Java, unübersichtliche Schleifen programmiert werden, was letztendlich auf die Eleganz der funktionalen Programmierung zurückzuführen ist [OSV10, S. 15 f.]. Eine wachsende Sprache Programme verschiedener Größe tendieren dazu, unterschiedliche Programmierkonstrukte zu benötigen. Hierfür besteht in Scala die Möglichkeit, bestehende Konstrukte individuell an eigene Belange anzupassen. Das wird möglich, da diese Gebilde nicht fest in der Sprachsyntax verankert sind. Sie sind Bibliotheksabstraktionen, die erweitert oder adaptiert werden können. Es ist beispielsweise denkbar von einer Standard Map ausgehend eine speziellere Map zu implementieren, wie etwa eine HashMap oder TreeMap. In jedem Fall ist es aber potenziell möglich die gleiche Eingangssyntax einer Map zu verwenden. Dies gilt auch für die in der Sprache eingesetzten Typen, welche zwar wie fest einge-

Christoph Schmidt

Seite 7 von 49

2. Grundlagenbetrachtung

Fachhochschule Schmalkalden SS 2011

baute Typen erscheinen, aber dennoch nur als Klassen der Scala standard Bibliothek 4 vorliegen. All diese Eigenschaften ermöglichen es vollkommen neue Abstraktionen zu schaffen, mit deren Hilfe neue anwendungsspezifische Sprachen entwickelt werden können, welche sich sehr weit einer natürlichen Sprache annähern [OSV10, S. 4 ff.]. Dies soll Listing 2.5 veranschaulichen. Listing 2.5: DSL zur Bestimmung eines Wochentages import java . util . Calendar class Date ( val data : Calendar ) { data . clear ( Calendar . HOUR ) import Date . Conjunction private var last = 0; def plus ( num : Int ) = { last = num ; this } def minus ( num : Int ) = { last = - num ; this } def years = { data . add ( Calendar . YEAR , last ) ; this } def years ( and : Conjunction ): Date = years def year = years def year ( and : Conjunction ): Date = years override def toString = data . get ( Calendar . DAY _ OF _ WEEK ) match { case 1 = > " Sunday " case 2 = > " Monday " /* ... */ } } object Date { class Conjunction val and = new Conjunction def Today = new Date ( Calendar . getInstance ) def Birthday = Today def Birthday ( day : Int , month : Int , year : Int ) = { var data = Calendar . getInstance data . set ( year , month - 1 , day ) new Date ( data ) } def today = Today def birthday = Birthday def birthday ( day : Int , month : Int , year : Int ) = Birthday ( day , month , year ) }
4

Weiterführende Informationen zur Scala standard Bibliothek sind unter http://www.scalalang.org/api/current/index.html#package zu finden.

Christoph Schmidt

Seite 8 von 49

2. Grundlagenbetrachtung

Fachhochschule Schmalkalden SS 2011

Die hier dargestellte domain specific language, kurz DSL, berechnet zu einem Geburtstag den entsprechenden Wochentag. Dabei ist es möglich zu diesem Tag beliebig viele Jahre hinzu zu addieren oder zu subtrahieren, um den Wochentag eines in der Zukunft oder Vergangenheit liegenden Geburtstags zu berechnen. Listing 2.6: Anwendungsbeispiel der DSL import java . util . Calendar import Date ._ object Example extends App { println ( birthday (16 ,8 ,1985) plus 26 years and minus 1 year and plus 1 year ) } Listing 2.6 zeigt wie zu einem Geburtstag mit Hilfe der plus Methode 26 Jahre hinzu addiert werden. Weiter wird dargestellt, dass sich Rechenoperationen wie minus einfach durch and anhängen lassen. Das hier dargestellte Beispiel würde als Wochentag einen Dienstag berechnen. Um das erreichen zu können, liefert birthday(16,8,1985) ein Objekt der Klasse Date zurück. Auf diesem Objekt wird anschließend die plus Methode aufgerufen. Der an diese Methode übergebene Zahlenwert wird in der Variablen last gespeichert. Die plus Methode gibt sich, also das Objekt, anschließend selbst zurück, worauf die years Methode angewendet wird. Mit Hilfe des Wertes and, welcher eine Instanz der Klasse Conjunction ist, lassen sich dann beliebig viele Rechenoperationen anhängen. Das zuvor dargestellte Beispiel dient lediglich der Veranschaulichung der Erweiterbarkeit von Scala. Es lässt sich daraus ableiten, wie die dort genutzten und zuvor vorgestellten Konzepte hierzu beitragen.

2.2 Lift
Lift ist ein Framework mit dessen Hilfe Webapplikationen mit Scala realisiert werden können. Dabei handelt es sich um ein Full Stack Web Application Framework. Dies bedeutet, dass Lift alles, was für die Entwicklung von Web-Applikationen benötigt wird, mitbringt [Bra10, S. 253]. Das Framework wurde entwickelt um sichere, performante und leicht wartbare Applikationen zu entwickeln [Per11, S. 5].

2.2.1 Architektur
Lift arbeitet nicht wie viele andere Web-Frameworks nach dem MVC -Muster. Lift verfolgt einen Denkansatz, der View First Design genannt wird. Dieser besteht aus den drei Bestandteilen View, Snippet und Model. Dadurch wird es, im Gegensatz zu MVC, möglich Seiten, die mehr als ein Element besitzen, innerhalb einer Anfrage zu erstellen, was in modernen Applikationen meist der Fall ist [Per11, S. 8]. Abbildung 2.1 zeigt das Zusammenspiel der einzelnen Komponenten, welche im Anschluss näher erläutert werden.

Christoph Schmidt

Seite 9 von 49

2. Grundlagenbetrachtung

Fachhochschule Schmalkalden SS 2011

Abbildung 2.1: View First Design

View Innerhalb des View First Kontext bezieht sich View primär auf XML Inhalte, die bei einer Seitenanfrage benötigt werden. Innerhalb von Lift-Anwendungen gibt es grundsätzlich zwei Arten von Views: • Template Views, die dynamische Inhalte in vordefinierte Markup Templates binden [Per11, S. 9]. • Erzeugte Views, in welchen typischerweise dynamische Inhalte mittels Scala XML Ausdrücken erzeugt werden [Per11, S. 9]. Template Views werden üblicherweise dafür eingesetzt um Inhalte einer View zu erzeugen. Dies setzt allerdings ein korrekt formatiertes XHTML oder HTML5 Template voraussetzt, da es in Lift nicht möglich ist Views einzusetzen, welche Formatierungsfehler aufweisen. Erzeugte Views sind weitaus weniger üblich, sie werden aber manchmal für eine schnelle Prototypenentwicklung verwendet. Als eine der Lift Hauptideen gilt, dass Views für mehr als eine einzige Aufgabe eingesetzt werden können. Das trägt dazu bei, um redundanten Quellcode innerhalb einer Anwendung zu verringern und ermöglicht es auch Komponenten zu entwickeln, welche voneinander entkapselt sind [Per11, S. 9 f.]. Snippet Snippets sind Darstellungsfunktionen, welche mittels Scala programmiert werden. Diese werden dann mit Hilfe von speziellen Tags in Templates eingebunden [Bra10, S. 262]. Sie bezwecken einzig das Erzeugen von dynamischen Inhalten und teilen Änderungen der Model-Komponente dem View mit [Per11, S. 10]. Sie sind typischerweise in Klassen zusammengefasst [Per11, S. 35]. Listing 2.7: Hallo-Welt Snippet package code . snippet import scala . xml . NodeSeq import net . liftweb . util . Helpers ._ class HalloWelt { def hallo = " * " # > < strong > Hallo Welt ! </ strong > }

Christoph Schmidt

Seite 10 von 49

2. Grundlagenbetrachtung

Fachhochschule Schmalkalden SS 2011

Listing 2.7 stellt eine Scala Klasse dar, welche eine Snippet Methode hallo definiert, die als CSS Transformer bezeichnet wird. Das sind im wesentlichen Funktionen, die als Eingabeparameter ein Element vom Typ NodeSeq5 erwarten und auch ein Element von NodeSeq zurückliefern. Diese werden durch das Importieren des Helpers._ Objektes unterstützt, welches eine entsprechende implizite Typumwandlung beinhaltet [Per11, S. 36]. Listing 2.8: Hallo-Welt Template <! -- ... -- > < body class =" lift : content _ id = main " > < div id =" main " class =" lift : surround ? with = default ; at = content " > <p lift =" HalloWelt . hallo " > Ersetze mich ! </p > </ div > </ body > <! -- ... -- > In Listing 2.8 ist ein Template dargestellt, welches die zuvor definierte hello Methode benutzt. Mittels des Schlüsselworts lift wird die Methode hallo der Klasse HalloWelt aufgerufen und das entsprechende Tag ersetzt. Da Snippet Klassen Darstellungsfunktionen beinhalten muss es eine Möglichkeit geben um Textfelder, Check-Boxen oder Buttons zu erstellen. Für diese Zwecke stellt Lift das Objekt net.liftweb.http.SHtml bereit, welches diese Aufgabe übernimmt [CBDW11, S. 25]. Model In diesem Zusammenhang ist Model eine allgemeine Bezeichnung, die mehrere Dinge darstellen kann. In den meisten Applikationen stellt dieser Teil ein Modell der Persistenz oder der Daten dar. Für gewöhnlich wird an dieser Komponente ein konkreter Wert nachgefragt, den diese dann zurückliefert [Per11, S. 10].

2.2.2 Lift Core und Lift Web
Lift besitzt zwei Module, die einen zentralen Teil des Frameworks ausmachen. Diese werden als Core und Web bezeichnet. Der Core setzt sich aus vier einzelnen Projekten zusammen. Diese beinhalten Bibliotheken, die sowohl mit als auch ohne das Web Modul in Projekten eingesetzt werden können. Das Web Modul selbst baut drauf auf und unterstützt die komplexen Komponenten von Lift um sichere und skalierbare Web-Anwendungen realisieren zu können. Das Web Modul setzt sich aus drei Teilprojekten zusammen: Das Basis Web System und zwei zusätzliche Projekte, die spezielle Helfer zur Verfügung stellen [Per11, S. 12]. Abbildung 2.2 zeigt eine Übersicht der einzelnen Bestandteile, welche im Anschluss näher erläutert werden.

5

NodeSeq ist in Scala eine Sequenz von XML Knoten.

Christoph Schmidt

Seite 11 von 49

2. Grundlagenbetrachtung

Fachhochschule Schmalkalden SS 2011

Abbildung 2.2: Module Lift Core/Web

Lift Common Dieses Modul beinhaltet eine Menge an Basisklassen, die überall in Lift eingesetzt werden können. Darüber hinaus können diese auch in Projekten genutzt werden, die keine Web-Anwendungen darstellen [Per11, S. 12]. Weiterführende Informationen zu diesem Paket sind in der API-Dokumentation 6 unter net.liftweb.common zu finden. Lift Actor Actor beschreibt ein Modell der nebenläufigen Programmierung. Im Scala-Umfeld gibt es zahlreiche verschiedene Implementierungen hierzu. Lift besitzt seine Eigene, speziell für den Bereich der Web-Programmierung [Per11, S. 13]. Diese ist im Paket net.liftweb.actor angesiedelt. Lift Utilities Utilities beschreibt eine Sammlung von Klassen, Traits und Objekten, welche entwickelt wurden um einen komfortablen Mechanismus zur Verfügung zu stellen, um mit häufig genutzten Paradigmen zu arbeiten [Per11, S. 13]. Ein genauer Überblick ist im Paket net.liftweb.util zu finden. Lift JSON Lift JSON stellt ein eigenständiges Paket dar, dass es ermöglicht mit JSON 7 auf eine sehr ressourcenschonende Art zu arbeiten. Im Vergleich mit dem JSON Parser, welchen Scala verwendet, ist dieser ungefähr 350 mal so schnell. Darüber hinaus stellt Lift eine durchdachte DSL für das Konstruieren von JSON Objekten bereit [Per11, S. 14]. Weitere Details sind im Paket net.liftweb.json bereitgestellt. Lift Webkit Dieses Modul beinhaltet den Einstiegspunkt des Frameworks. Es setzt sich aus der Anfrageverarbeitung, deren Lokalisierung sowie der Template-Darstellung zusammen. Es ist das wichtigste Modul von Lift [Per11, S. 14].

6 7

http://scala-tools.org/mvnsites/liftweb-2.3 JSON ist ein Kurzwort für JavaScript Object Notation.

Christoph Schmidt

Seite 12 von 49

2. Grundlagenbetrachtung

Fachhochschule Schmalkalden SS 2011

2.2.3 Persistenz
Eine der Hauptaufgaben von Web-Anwendungen befasst sich mit der dauerhaften Speicherung von Daten. Für diese Zwecke stellt Lift ein Mapper und Record Framework zur Verfügung. Diese Frameworks stellen ein Gerüst für jegliche Datenmanipulation bereit. Mapper stellt das ursprüngliche Persistenz-Framework dar, welches eng mit JDBC 8 verknüpft ist [CBDW11, S. 89]. Auf diese Art und Weise stellt Lift verschiedene Optionen zur Verfügung um Daten zu speichern. Dabei ist es irrelevant ob es sich bei der zu Grunde liegenden Technologie um ein relationales Datenbankmanagementsystem (RDBMS) oder eine NoSQL9 Lösung handelt [Per11, S. 16]. Abbildung 2.3: Struktur der Lift-Persistenz

Abbildung 2.3 illustriert eine strukturelle Übersicht der Persistenz. Im Anschluss werden die wichtigsten Bestandteile näher ausgeführt. DB/Mapper Mapper bieten eine einheitliche Möglichkeit um mit persistenten Daten zu arbeiten. Das Framework stellt einen O/R-Mapper 10 bereit, welcher alle relationalen Beziehungen verarbeiten kann (z. B. 1:1, 1:N und M:N Beziehungen). Daher ist es nicht zwingend erforderlich SQL Join Anfragen 11 zu programmieren [Per11, S. 16]. Weiterführende Informationen sind im Paket net.liftweb.mapper zu finden. Lift JPA Die Java Persistence API ist im Java Umfeld weit verbreitet. Daher wurde diese zu Lift hinzugefügt und an Scala angepasst [Per11, S. 17]. Alle relevanten Daten sind im Paket net.liftweb.jpa bereitgestellt. Lift Record Die Records repräsentieren eine Sicht, die dem Benutzer Create, Read, Update und Delete Semantik für die Datenmanipulation bereitstellt. Außerdem bietet diese eine Menge an Optionen um beispielsweise Form-Felder darzustellen [Per11, S. 17 f.]. Dabei spielt es keine Rolle, ob die Daten mit JDBC, JPA oder sogar in Form von XML gespeichert werden [CBDW11, S. 89].

JDBC ist eine Datenbankschnittstelle der Java-Plattform. NoSQL: Steht für englisch Not only SQL. 10 O/R Mapper bezeichnet eine Programmiertechnik um Daten zwischen inkompatiblen TypSystemen zu transformieren. 11 SQL Join Anfrage kombiniert Datensätze zweier oder mehrerer Tabellen einer Datenbank.
9

8

Christoph Schmidt

Seite 13 von 49

2. Grundlagenbetrachtung

Fachhochschule Schmalkalden SS 2011

2.2.4 Projektstruktur
In diesem Abschnitt wird die Projektstruktur einer Lift-Anwendung vorgestellt. Dabei beziehen sich alle Angaben auf das von Lift bereit gestellte lift_basic 12 -Projekt. Listing 2.9: Projektstruktur |-| | | | ‘-project | - - build | ‘-- LiftProject . scala ‘-- build . properties src |-| | | | | | | | | | | | | | | | | | | | | | | | | | | ‘--

main | - - resources | ‘-- props | ‘-- default . props | - - scala | | - - bootstrap | | ‘-- liftweb | | ‘-- Boot . scala | ‘-- code | | - - comet | | - - lib | | ‘-- DependencyFactory . scala | | - - model | | ‘-- User . scala | | - - snippet | | ‘-- HelloWorld . scala | ‘-- view ‘-- webapp | - - images | ‘-- ajax - loader . gif | - - index . html | - - static | ‘-- index . html | - - templates - hidden | | - - default . html | ‘-- wizard - all . html ‘-- WEB - INF ‘-- web . xml test ...

Im Ordner project werden alle Informationen die zum Erstellen der Anwendung mit dem Build-Tool SBT notwendig sind aufbewahrt, welches in Abschnitt 5.1.2 vorgestellt wird. In diesem Ordner ist auch eine Datei LiftProject.scala zu finden.
12

https://github.com/lift/lift_23_sbt/tarball/master

Christoph Schmidt

Seite 14 von 49

2. Grundlagenbetrachtung

Fachhochschule Schmalkalden SS 2011

Sie beinhaltet beispielsweise Abhängigkeiten wie benötigte Repositories und wird mit Hilfe von Scala konfiguriert [Per11, S. 31]. In der Datei resources/props/default.props können Properties definiert werden, auf welche dann in der Anwendung zugegriffen werden kann. Sie enthält normalerweise keine Einträge. Das Verzeichnis scala beherbergt die eigentlichen Scala-Dateien der Anwendung. Es ist mit verschiedenen Unterverzeichnissen ausgestattet um das Projekt zu strukturieren. Die Datei bootstrap/liftweb/Boot.scala wird beim booten der Anwendung genutzt und wird in Abschnitt 2.2.5 näher ausgeführt. Alle anwendungsspezifischen Klassen und Objekte befinden sich im Verzeichnis code. Alle sonstigen für die Anwendung wichtigen Dateien wie Bilder, statische HTMLSeiten und Templates werden im Verzeichnis src/main/webapp aufbewahrt [Bra10, S. 256].

2.2.5 Konfiguration
Bevor Lift eine Anwendung startet müssen einige Dinge konfiguriert werden, so dass überhaupt eine Anfrage ausgeführt werden kann. Der Lift Servlet 13 sucht nach einer Klasse bootstrap.liftweb.Boot und führt dessen boot Methode aus. Diese Methode wird nur einmalig ausgeführt und eignet sich daher um Initialisierungsaufrufe anderer Bibliotheken in ihr zu platzieren [CBDW11, S. 24]. Listing 2.10 zeigt einen Auszug einer boot Mehtode, welche im Anschluss näher ausgeführt wird. Als Erstes wird mit dem StandardDBVendor Objekt eine Datenbankverbindung hergestellt, welches eine H2-Datenbank 14 verwaltet [Bra10, S. 257]. Anschließend wird mit Hilfe des LiftRules Objektes der unloadHooks Collection eine Funktion angehängt, die für das Schließen aller Datenbankverbindungen verantwortlich ist. Diese wird ausgeführt, wenn die Anwendung heruntergefahren wird [Bra10, S. 258]. Durch den Schemifier kommt ein Teil des O/R-Mappers zum Einsatz. Durch dessen schemify Methode wird gewährleistet, dass die Datenbank das korrekte Schema eines User Objektes besitzt, um User zu speichern [Bra10, S. 258]. Ein User-Objekt könnte wie in der in Abschnitt 2.2.4 eingeführten Beispiel-Anwendung aufgebaut sein, welches in der Datei code/model/User.scala zu finden ist. In der anschließenden Zeile wird Lift mittels LiftRules.addToPackages("code") bekannt gegeben, in welchem Paket das Framework nach Quellcode, z. B. für Snippets, suchen soll [Bra10, S. 258]. Dann wird die Menüsteuerung implementiert, was durch die Methode sitemap erzielt wird. An dieser Stelle sei erwähnt, dass Lift bereits über eine eingebaute Menüsteuerung und Zugriffsverwaltung verfügt, deren Funktionsweise im Kapitel 5.2 näher erläutert wird.

13

Mit Servlets werden Java-Klassen bezeichnet, deren Instanzen innerhalb eines Java-Webservers Anfragen von Clients entgegen nehmen und beantworten. 14 http://www.h2database.com

Christoph Schmidt

Seite 15 von 49

2. Grundlagenbetrachtung

Fachhochschule Schmalkalden SS 2011

Listing 2.10: Die Methode boot def boot { val vendor = new StandardDBVendor ( " org . h2 . Driver " , " jdbc : h2 : lift _ proto . db ; AUTO _ SERVER = TRUE " , Empty , Empty ) LiftRules . unloadHooks . append ( vendor . closeAllConnections _! _) DB . defineConnectionManager ( DefaultConnectionIdentifier , vendor ) Schemifier . schemify ( true , Schemifier . infoF _ , User ) LiftRules . addToPackages ( " code " ) def sitemap = SiteMap ( Menu . i ( " Home " ) / " index " >> User . AddUserMenusAfter , Menu ( Loc ( " Static " , Link ( List ( " static " ) , true , " / static / index " ) , " Static Content " ) ) ) def sitemapMutators = User . sitemapMutator LiftRules . setSiteMapFunc (() = > sitemapMutators ( sitemap ) ) /* ... */ S . addAround ( DB . buildLoanWrapper ) } In Listing 2.10 wurden einige Objekte verwendet, die in Lift eine fundamentale Rolle spielen. Deshalb sollen diese im Anschluss kurz vorgestellt werden. S Objekt Das net.liftweb.http.S Objekt repräsentiert den Zustand der aktuellen Anfrage. Es wird beispielsweise benutzt, um Informationen abzufragen und um Informationen, die in der Antwort gesendet werden, zu modifizieren. Es kann unter anderem auch für das Cookie-Management oder für eine Redirection verwendet werden [CBDW11, S. 25]. LiftRules Das Objekt net.liftweb.http.LiftRules wird eingesetzt um die globale Konfiguration eines Lift-Projekts zu realisieren. Alles was in Lift konfiguriert werden kann wird über Variablen dieses Objekts umgesetzt [CBDW11, S. 25].

Christoph Schmidt

Seite 16 von 49

3 Analyse
In Zusammenarbeit mit dem Studiendekan und Stundenplaner der Fakultät Informatik wurde die bisherige Planungssoftware zum Erfassen und Planen des Curriculums untersucht um daraus die grundsätzlichen Anforderungen an eine webbasierte Neuimplementierung mit dem Namen PlanningWeb abzuleiten. Die daraus resultierenden Ergebnisse werden in den folgenden Abschnitten vorgestellt. Der Analyseprozess wurde in Anlehnung an [OB09, S. 89 ff.] durchgeführt.

3.1 Zielsystem
PlanningWeb ist eine Software, die den Studiendekan in allen wichtigen Anwendungsfällen der Lehrplanung unterstützt. Die daraus resultierenden Ergebnisse bilden die Grundlage für die Stundenplanung des jeweiligen Semesters. Darüber hinaus soll das System den Stundenplaner bei der Erfassung der Arbeitszeiten und Raumwünsche der Dozenten unterstützen. Es können Dozenten, Studiengänge, Lehrveranstaltungen und Räume mit allen planungsrelevanten Daten erfasst, geändert und gelöscht werden. Nach Abschluss der Lehrplanung können die Ergebnisse des Planungsprozesses für das externe Stundenplanungssystem bereitgestellt werden. Außerdem können sich Dozenten am System anmelden um Arbeitszeit- oder Raumwünsche zu äußern, die der Stundenplaner anschließend im Planungsprozess berücksichtigen kann. Die Software verfügt über eine Zugriffskontrolle, mit der es möglich ist Benutzer am System anzumelden. Die Authentifizierung wird mit Hilfe einer gültigen FHS-ID 1 unter Zuhilfenahme des FH internen LDAP 2 -Servers durchgeführt. Der Kern der Anwendung setzt einen Server mit Unix/Linux oder Windows als Betriebssystem voraus. Auf ihm muss ein Application-Server wie Jetty oder Tomcat installiert und konfiguriert sein. Der Anwendungsserver muss sich im Netz der Fachhochschule befinden. Das System ist datenbankunabhägig und kann sowohl mit NoSQL3 - als auch relationalen Datenbanken betrieben werden. Die Anwendung wird von allen gängigen Internetbrowsern unterstützt und ermöglicht plattformunabhäniges Arbeiten.

3.2 Benutzeranalyse
Nachdem im vorangegangen Abschnitt das Zielsystem beschrieben wurde, sollen hier die späteren Benutzer analysiert und klassifiziert werden. Aus den Gesprächen
1 2

FHS-ID ist eine von der FH vergebene ID zur eindeutigen Identifizierung. LDAP: Lightweight Directory Access Protocol [Sem06]. 3 NoSQL: Steht für englisch Not only SQL.

Christoph Schmidt

Seite 17 von 49

3. Analyse

Fachhochschule Schmalkalden SS 2011

mit dem Studiendekan und Stundenplaner lassen sich grundsätzlich drei Benutzergruppen ableiten: Lehrplaner, Stundenplaner und Dozenten. Dazu kommt noch ein Administrator, der die Anwendung betreut. Um zu verhindern, dass die Daten einer Abbildung 3.1: Systemkontextdiagramm

bestimmten Benutzergruppe von anderen Benutzergruppen gelesen oder manipuliert werden, ist es notwendig für die einzelnen Benutzergruppen Rollen zu vergeben. Dies sind: • Lehrplaner mit Zugriff auf Dozenten, Studiengänge und Lehrveranstaltungen. • Stundenplaner mit Zugriff auf Arbeitszeiten der Dozenten, Räume und durch den Lehrplaner freigegebene Lehrveranstaltungen zur Stundenplanung. • Dozent mit Zugriff auf eigene Arbeitszeiten und Wunschräume. • Administrator mit Zugriff auf alle Daten.

3.3 Anwendungsfälle
Durch die Klassifizierung der Benutzer im Abschnitt 3.2 ist es möglich entsprechend den Rollen Anwendungsfälle abzuleiten. Diese ermöglichen es die Hauptaufgabe des Systems darzustellen um im weiteren Verlauf ein flexibles Design entwerfen zu können. [OB09, S. 114]. Es werden nur die Anwendungsfälle des Planungsprozesses und der Arbeitszeiterfassung von Dozenten als Essenzbeschreibung 4 dargestellt, da diese für das weitere Verständnis von wesentlicher Bedeutung sind.

4

Essenzbeschreibung ist die komprimierteste und abstrakteste Form eines Anwendungsfalls [OB09, S. 114].

Christoph Schmidt

Seite 18 von 49

3. Analyse

Fachhochschule Schmalkalden SS 2011

3.3.1 Lehrplanungsprozess
Die Planung des Curriculums umfasst mehrere Schritte. Sie beginnt mit dem Zuweisen einer Veranstaltung zu einem Semester, wie in Tabelle 3.1 dargestellt. Tabelle 3.1: Anwendungsfall Lehrveranstaltung Semester zuweisen
Name Kurzbeschreibung Auslöser Akteur Vorbedingung Nachbedingung Essenzielle Schritte Lehrveranstaltung Semester zuweisen Der Lehrplaner weist Lehrveranstaltung einem Semester zu. Es ist eine neue Lehrplanung für Sommer- oder Wintersemester erforderlich Der Lehrplaner. Es ist mindestens eine Lehrveranstaltung im System vorhanden. Lehrveranstaltung wurde einem Semester zugewiesen. alle Lehrveranstaltungen anzeigen; gewünschte Lehrveranstaltung Semester zuweisen; Änderungen speichern; Speicherung bestätigen

Anschließend besteht die Möglichkeit Vorlesungsgruppen zu erstellen, um die einzelnen Semester des gleichen oder eines anderen Studiengangs, die laut Studienordnung an dieser Veranstaltung teilnehmen, auf einen oder mehrere Dozenten zu verteilen, was in Tabelle 3.2 abgebildet ist. Desweiteren ist es möglich Übungsgruppen für eine Lehrveranstaltung anzulegen. Da dieser Anwendungsschritt aber analog zu dem Erstellen einer Vorlesungsgruppe zu sehen ist, wird dieser Anwendungsfall nicht explizit aufgeführt. Tabelle 3.2: Anwendungsfall Vorlesungsgruppe erstellen
Name Kurzbeschreibung Auslöser Akteur Vorbedingung Nachbedingung Essenzielle Schritte Vorlesungsgruppe erstellen Der Lehrplaner erstellt eine Vorlesungsgruppe für eine Lehrveranstaltung. Die Anzahl der Teilnehmer einer Lehrveranstaltung ist zu groß und soll daher mehrfach angeboten werden. Der Lehrplaner. Es ist mindestens eine Lehrveranstaltung im System vorhanden. Vorlesungsgruppe wurde für eine Lehrveranstaltung erstellt. eine Lehrveranstaltung auswählen; Studiengänge einer Lehrveranstaltung mit zugehörigem Semester anzeigen; Studiengänge mit entsprechendem Semester auswählen, alle Dozenten für Lehrveranstaltung anzeigen, die diese Vorlesung halten; ein oder mehrere Dozenten auswählen; Vorlesungsgruppe speichern; Speicherung bestätigen

Nachdem die Planungsphase der Vorlesungs- und Übungsgruppen abgeschlossen ist, müssen aus den erfassten Daten noch die konkreten Vorlesungen und Übungen abgeleitet werden, die in einer Studienwoche eines Semesters angeboten werden sollen. Das Semester kann Sommer- oder Wintersemester sein. Diese Daten dienen dann

Christoph Schmidt

Seite 19 von 49

3. Analyse

Fachhochschule Schmalkalden SS 2011

dem Stundenplaner als Basis für die entsprechende Stundenplanung. Der zugehörige Anwendungsfall ist in Tabelle 3.3 dargestellt. Tabelle 3.3: Anwendungsfall Semesterplanung
Name Kurzbeschreibung Semesterplanung Der Lehrplaner generiert die konkreten Vorlesungen und Übungen für alle Lehrveranstaltungen eines bestimmten Semesters. Die Planung des Curriculums ist abgeschlossen. Der Lehrplaner. Es ist mindestens eine Lehrveranstaltung im System vorhanden und Sommer- oder Wintersemester zugeordnet. Konkrete Vorlesungen und Übungen sind im System erfasst. Sommer- oder Wintersemester zum Planen auswählen; entsprechende Vorlesungen und Übungen aus Lehrveranstaltungen generieren; erstellte Vorlesungen und Übungen anzeigen; alle angezeigten Vorlesungen und Übungen speichern; Speicherung bestätigen

Auslöser Akteur Vorbedingung Nachbedingung Essenzielle Schritte

3.3.2 Arbeitszeiterfassungsprozess
Die Erfassung der Arbeitszeiten und Wunschräume einzelner Dozenten umfasst einen weiteren wichtigen Bestandteil der Anwendung, was in Tabelle 3.4 dargestellt ist. Die dabei erfassten Raum- und Zeitwünsche dienen später dem Stundenplaner als Basis für die Stundenplanung. Tabelle 3.4: Anwendungsfall Arbeitszeit und Raumwünsche erfassen
Name Kurzbeschreibung Arbeitszeit und Raumwünsche eines Dozenten erfassen Der Dozent wählt aus einer vorgegebenen Menge von Zeiteinheiten Arbeitszeiten aus. Anschließend markiert er Wunschräume für seine zu haltenden Lehrveranstaltungen. Die Zeiterfassung wurde durch den Stundenplaner freigeschaltet. Stundenplaner und Dozent. Es ist mindestens ein Dozent mit FHS-ID im System bekannt. Konkrete Arbeitszeiten und Wunschräume des Dozenten sind im System erfasst. Wunsch- u. Kann-Zeiten auswählen; Wunschräume Lehrveranstaltungen zuweisen; prüfen ob ausreichend Arbeitszeiten markiert wurden; wenn ja Speichern; wenn nein, Warnung ausgeben und Eingaben zurücksetzen

Auslöser Akteur Vorbedingung Nachbedingung Essenzielle Schritte

Christoph Schmidt

Seite 20 von 49

4 Design
Nachdem im vorangegangen Kapitel 3 das Zielsystem genau beschrieben und analysiert wurde, wird in diesem Abschnitt auf das Design der PlanningWeb-Anwendung eingegangen. Dabei ist festzuhalten, dass die gegebene Aufgabenstellung bereits eine Client/Server-Architektur voraussetzt. Prinzipiell kann die Architektur in verschiedene Schichten aufgeteilt werden, um eine Abgrenzung zwischen Funktionalität und Aufgaben zu erzielen [Mü05, S. 62]. Im Folgenden wird daher kurz die Drei- und Vier-Schichten-Architektur vorgestellt um darauf aufbauend die Details des PlanningWeb-Designs zu erläutern. Im Bereich der Softwarearchitektur spielt aber nicht nur die Aufteilung eines Softwaresystems in Schichten eine Rolle. Moderne Softwaresysteme sind zudem meist in Komponenten aufgeteilt. Daher soll im Anschluss an die Schichtenarchitektur noch der Komponentenbegriff konkretisiert werden.

4.1 Drei-Schichten-Architektur
In dieser Architektur wird die Anwendungs- von der Präsentationslogik getrennt, was zur Folge hat, dass der Client ausschließlich die Präsentationslogik enthält. Die Anwendungslogik wird auf einem Applikationsserver bereitgestellt, die den Client mit dem Datenbank-Server verbindet [Mü05, S. 64 f.].

4.2 Vier-Schichten-Architektur
Im Vergleich zur Drei-Schichten-Architektur ändert sich bei Hinzunahme einer weiteren Schicht, dass sich die Präsentationslogik vom Client auf einen Webserver verschiebt. Die Anwendungslogik ist weiterhin im Applikationserver angesiedelt. Dadurch stellt der Client nur noch eine Schnittstelle für den Benutzer dar, welche die eingegebenen Daten an den Server weiterleitet. Außerdem dient der Client dazu die vom Server angeforderten Daten darzustellen. Durch diese Architektur können browserbasierte Internet-Anwendungen realisiert werden [Mü05, S. 65 f.].

4.3 Softwarekomponenten
Technische Systeme bestehen zumeist aus Komponenten. Im Bereich der Softwareentwicklung hat sich jedoch bislang keine allgemein akzeptierte Definition etabliert. Es lassen sich aber allgemeingültige Merkmale darstellen, die eine Komponente kennzeichnen [Sie04, S. 42].

Christoph Schmidt

Seite 21 von 49

4. Design

Fachhochschule Schmalkalden SS 2011

• Eine Komponente importiert andere Schnittstellen [Sie04, S. 43]. • Eine Komponente verbirgt die Implementierung und kann daher durch andere Komponenten ersetzt werden [Sie04, S. 43]. • Sie können wiederverwendet werden, da sie von der Umgebung in der sie eingesetzt werden unabhängig sind [Sie04, S. 43]. • Sie lassen sich beliebig kombinieren um so neue Komponenten zu erzeugen [Sie04, S. 43]. • Komponenten sind ein wichtiger Bestandteil des Entwurfs und der Implementierung [Sie04, S. 43].

4.4 Konkretes Design
Die in Abschnitt 4.2 vorgestellte Architektur lässt sich auch auf die PlanninWebApplikation übertragen. Das Anfordern einer Ressource eines Clients vom Server läuft dann folgendermaßen ab: • Client fordert eine Ressource an. • Webserver nimmt die Anfrage entgegen. Anschließend wendet sich der Webserver an den Applikationserver um die angeforderten Daten in einer geeigneten Präsentationsform an den Client zurückzusenden. • Applikationserver fordert die benötigten Daten von der Datenbank an und generiert auf Basis der Anwendungslogik das Ergebnis und übergibt dies an den Webserver, der dann die angeforderten Daten in geeigneter Präsentationsform an den Client sendet. Durch die Rahmenbedingungen des SPIRIT-Projekts in Kapitel 1.3 ist die Wahl des Webservers bereits auf Jetty festgesetzt, da dieser dort bereits im Einsatz ist. Jetty bietet den Vorteil, dass er die Funktion eines Webservers mit der eines Applikationservers vereint. Das nachfolgende Diagramm 4.1 stellt die einzelnen Komponenten des Systems genauer dar, die im Anschluss ausführlich erläutert werden.

4.4.1 Datenhaltung
Wie in Kapitel 2.2.3 dargestellt, verfügt Lift über ein Mapper und Record Framework welches auch in der PlanningWeb-Anwendung zum Einsatz kommt. Allerdings soll das geplante System datenbankunabhänig implementiert werden. Auf Grund dieses Umstandes kann das Framework nur indirekt genutzt werden. Daher befinden sich im Kern der Anwendung zwei Komponenten persistence und transform. Um die Hintergründe dieser Komponenten zu verstehen sollen erst zwei Entwurfsmuster vorgestellt werden.

Christoph Schmidt

Seite 22 von 49

4. Design

Fachhochschule Schmalkalden SS 2011

Abbildung 4.1: Komponentendiagramm

Active Record Bei diesem Entwurfsmuster enthalten Objekte sowohl Daten als auch Verhaltensweisen. Die meisten dieser Daten sind persistent und müssen daher in einer Datenbank gespeichert werden. Active Record benutzt den klarsten Ansatz um Datenbankzugriffslogik in einem Anwendungsobjekt unterzubringen. So wissen alle Nutzer wie Daten von der Datenbank gelesen und geschrieben werden können. Daraus folgt auch, dass die Struktur eines Records genau auf die darunterliegende Datenbankstruktur abgebildet werden kann. Dieses Muster ist für Anwendungen geeignet, die einen geringen Komplexitätsgrad aufweisen. Allerdings koppelt Active Record die Anwendungslogik direkt an die Datenbank, was zur Folge hat, dass Designänderungen nur schwer durchzuführen sind [FRF+ 03, S. 160 ff.]. Data Mapper Das Data Mapper Muster lässt sich am besten mit Hilfe eines Beispiels erklären. Angenommen es existiert eine Klasse Person und eine zugehörige Klasse PersonMapper. Um ein Personen-Objekt aus der Datenbank zu laden würde ein Client die find Methode des Mappers aufrufen. Dieser würde dann das entsprechende Objekt aus der Datenbank holen und als Ergebnis das entsprechende Personen-Objekt zurückgeben. Würde ein Client ein Objekt speichern wollen, würde das Objekt an den Mapper übergeben werden und dieser würde das Objekt in der Datenbank speichern. Dieses Entwurfsmuster kann so implementiert werden, dass für jede Klasse die in der Datenbank gespeichert werden soll, ein eigener Mapper erstellt werden muss. Es ist aber auch möglich das Muster so umzusetzen, dass in der gesamten Anwendung

Christoph Schmidt

Seite 23 von 49

4. Design

Fachhochschule Schmalkalden SS 2011

nur ein Mapper für alle Objekt eingesetzt wird. Außerdem kann das Muster auch dafür verwendet werden, um die Anwendung von der darunterliegenden Datenbank abzutrennen [FRF+ 03, S. 166 ff.]. Architektur Wie eingangs erwähnt besitzt Lift bereits Records für alle gängigen Datenbanken. Diese sind aber, wie beim Active Record Muster beschrieben, stark an die Datenbank gebunden. Deshalb wurden in der PlanningWeb-Anwendung die Komponenten persistence und transform eingeführt. Diese sind in Anlehnung an das Data Mapper Muster implementiert. Dabei wurde ein Ansatz verfolgt, ähnlich wie in [Sie04, S. 211 ff.] beschrieben. Die persistence Komponente bietet eine Schnittstelle an um Objekte in einer Datenbank zu lesen, zu schreiben, zu löschen und zu aktualisieren. Um das bewerkstelligen zu können benutzt die persistence Komponente eine Schnittstelle, die von der transform Komponente angeboten wird. Diese ist wiederum in der Lage Objekte der Anwendungslogik in Record-Objekte der entsprechenden Datenbank-Records zu transformieren um so das Lesen, Schreiben und Ändern von Objekten in der Datenbank zu ermöglichen. Durch diese Art der Architektur ist die Anwendungslogik komplett von der zugrundeliegenden Datenbank unabhängig und kann jederzeit gegen eine andere Datenbank ausgetauscht werden. Die nachfolgende Abbildung 4.2 stellt das Zusammenspiel der beiden Komponenten in einem Klassendiagramm dar.

Abbildung 4.2: Klassendiagramm Persistenz

Christoph Schmidt

Seite 24 von 49

4. Design

Fachhochschule Schmalkalden SS 2011

4.4.2 Anwendungskern
Der Anwendungskern im Allgemeinen beschreibt die fachliche Intelligenz der Anwendung [Sie04, S. 165]. In der PlanningWeb-Anwendung ist dieser Teil in der snippet Komponente angesiedelt, welche bereits in Kapitel 2.2.1 eingeführt wurde. Diese lässt sich gemäß der durchgeführten Analyse wiederum in eigenständige Teilkomponenten zerlegen, woraus fünf weitere Komponenten entstehen, die im Anschluss näher erläutert werden. • Studiengangsverwaltung: Ein wichtiger Bestandteil der Lehr- und Stundenplanung sind die Studiengänge. Ein Studiengang besitzt einen Namen, eine Abkürzung und eine Semesteranzahl. Darüber hinaus besitzt jedes Semester eine Anzahl an Studenten. Das System besitzt daher eine Studiengangsverwaltung mit folgenden Funktionen: Anlegen eines neuen Studiengangs, Bearbeiten eines Studiengans und Löschen eines Studiengangs. • Dozentenverwaltung: Um überhaupt Lehrveranstaltungen anbieten zu können sind Dozenten erforderlich, die bestimmte Vorlesungen anbieten. Ein Dozent besitzt einen Typ der sich aus einem Namen, den zu haltenden Pflichtstunden und einer Kennzeichnung, ob es sich bei diesem Typ um einen Lehrbeauftragen handelt, zusammensetzt. Außerdem gibt es auf Grund der FH internen LDAP-Struktur einen Dozenten für die Lehrplanung und einen FHS-Dozenten für die Authentifizierung am System. Ein Dozent besitzt einen Namen, der diesen eindeutig identifiziert, einen Typ und eine Zeitangabe zur Selbstverwaltung, die von den zu haltenden Pflichtstunden des Typs abgezogen wird um die tatsächliche Arbeitszeit zu ermitteln. Ein FHS-Dozent setzt sich wiederum aus einem Dozenten und einer FHS-ID zusammen. Die Studiengangsverwaltung besitzt deshalb diese Funktionen: Typen und FHS-Dozenten anzulegen und zu löschen. Dozenten können darüber hinaus angelegt, geändert und gelöscht werden. • Lehrveranstaltungsverwaltung: Kern einer jeden Lehrplanung sind die Lehrveranstaltungen. Eine Lehrveranstaltung setzt sich aus einem Typ, einem Namen der diese eindeutig identifiziert, Studiengängen mit entsprechenden Semestern, Dozenten sowie Vorlesungs- und Übungswochenstunden zusammen. Die Lehrveranstaltungsverwaltung bietet daher folgende Funktionen an: Erstellen und Löschen eines Typs; Erstellen, Ändern, Anzeigen und Löschen von Lehrveranstaltungen; Zuweisen von Lehrveranstaltungen zu Sommer- oder Wintersemester; Erstellen und Löschen von Lehrveranstaltungs- und Übungsgruppen sowie der Semesterplanung, welche die entsprechenden Veranstaltungen pro Studienwoche generiert. • Raumverwaltung: Ein wichtiger Bestandteil der Stundenplanung sind Räume. Ein Raum ist genau einem Gebäude zugeordnet und besitzt eine Bezeichnung, eine Raumgröße sowie zahlreiche Ausstattungsmerkmale (z. B. mit/ohne Tageslichtprojektor, Tafel, Beamer ...). Die Raumverwaltung bietet die Möglichkeit Räume zu Erstellen und zu Löschen.

Christoph Schmidt

Seite 25 von 49

4. Design

Fachhochschule Schmalkalden SS 2011

• Arbeitszeitverwaltung: Die Arbeitszeiten der Dozenten bilden einen weiteren Bestandteil der Stundenplanung. Die Arbeitszeiten setzen sich daher aus verschieden Zeiteinheiten einer Studienwoche zusammen. Die Arbeitszeitverwaltung bietet daher die Möglichkeit an, Arbeitszeiten und Raumwünsche für Veranstaltungen der einzelnen Dozenten zu erfassen und zu verwalten. Diese vorgestellten Funktionsgruppen besitzen gemäß ihrer Aufgaben Abhängigkeiten. Die Dozentenverwaltung ist wie die Studiengangs- und Raumverwaltung eigenständig. Die Arbeitszeitverwaltung hingegen ist auf die Dozenten-, Raum- und Lehrveranstaltungsverwaltung angewiesen. Den Kern des PlanningWeb-Systems bildet die Lehrveranstaltungsverwaltung. Sie ist wiederum von der Dozenten- und Studiengangsverwaltung abhängig. Auf Grund dieser Beziehungen lässt sich ein vereinfachtes Datenmodell ableiten, das in Abbildung 4.3 dargestellt ist. Abbildung 4.3: Datenmodell der PlanningWeb-Anwendung

In dem in Abbildung 4.3 vorgestellten Datenmodell kommt der Lehrveranstaltung oder auch Lecture eine zentrale Rolle zu. Deshalb wird diese aus dem Datenmodell herausgegriffen und deren Architektur ausführlich dargestellt. Abbildung 4.4 zeigt das Design einer Lehrveranstaltung wie es in der PlanningWeb-Anwendung umgesetzt ist. Eine Lehrveranstaltung besteht aus einem Name, der diese eindeutig beschreibt, einem Lehrveranstaltungstyp der sich aus der Studienordnung ergibt, einer Semesterwochenstudenanzahl für Übungen und Vorlesungen sowie zwei Flags, welche aussagen, ob die Lehrveranstaltung im Sommer- oder Wintersemester angeboten wird. Darüber hinaus enthält sie eine Liste mit Studiengangsinformationen, welche in der Klasse CourseInformation abgebildet sind. Eine CourseInformation setzt sich wiederum aus einem Course mit einer Liste entsprechender Semester zusammen, wie in Klasse Semester dargestellt. Eine Instanz der Klasse Semester besitzt einen Namen und eine Teilnehmerzahl. Die Klasse CourseInformation besitzt weiter eine Liste mit Dozenteninformationen, welche durch die Klasse DozentInformation repräsentiert werden. Diese Klasse bildet ab, ob ein Dozent eine Vorlesung und/oder eine Übung der Lehrveranstaltung abhält. Aus diesem Teilaufbau einer Lehrveranstaltung lassen sich bereits konkrete Vorlesungen und Übungen einer Studienwoche ableiten, die allerdings noch nicht alle geforderten Anforderungen erfüllt, wie beispielhaft in Listing 4.1 dargestellt.

Christoph Schmidt

Seite 26 von 49

4. Design

Fachhochschule Schmalkalden SS 2011

Abbildung 4.4: Klassendiagramm einer Lehrveranstaltung

Listing 4.1: Darstellung einer Lehrveranstaltung val lecture = Lecture ( " Prozedurale Programmierung " , LectureType ( " Pflichtfach " ) , List ( CourseInformation ( " Bachelor Informatik " ," BaI " , List ( Semester (1 ,1) ) , List ( SemesterInformation ( 1 , List ( DozentInformation ( Dozent ( " Braun " ," " ,0.0 , DozentType ( " Professor " ,18 , false ) ) , true , true ) ) ) ) ) ) , List () , List () ,1 ,1 , true , false )

Christoph Schmidt

Seite 27 von 49

4. Design

Fachhochschule Schmalkalden SS 2011

Aus Listing 4.1 lässt sich eine Vorlesungseinheit und eine Übungseinheit für das erste Semester des Studiengangs Bachelor Informatik mit der Lehrveranstaltungsbezeichnung Prozedurale Programmierung ableiten. Beide Termine werden vom Dozenten Braun im Sommersemester angeboten. Um weitere Anforderungen, wie das Erstellen von Übungs- und Vorlesungsgruppen, die flexibel einem oder mehren Dozenten zugewiesen werden können, enthält das Design einer Lehrveranstaltung zwei weitere Attribute, hasLectureTogetherWith und hasTutorialTogetherWith. Beide aggregieren die Klasse LectureRelationship, welche eine Liste mit Studiengängen und zugehörigem Semester in eine direkte Beziehung zu einem Dozenten setzen. Durch diese Architekturentscheidung können die in Kapitel 3.3.1 geforderten Anforderungen erfüllt werden.

Christoph Schmidt

Seite 28 von 49

5 Implementierung
Nachdem in den vorangegangenen Kapiteln die Sprache Scala und das Lift-Framework vorgestellt und die Anforderungen sowie das Design der Beispielanwendung entworfen und analysiert wurden, geht dieses Kapitel auf die Implementierung der PlanningWeb-Applikation ein. Es werden wichtige Programmteile ausführlich untersucht. Dabei werden Möglichkeiten vorgestellt, die das Lift-Framework und Scala bieten um spezifische Probleme zu lösen. Zu Beginn wird kurz ein Überblick über Programme gegeben, mit denen grundsätzlich Lift-Anwendungen realisiert werden können. Anschließend wird auf die Implementierung der wichtigsten Komponenten des Systems eingegangen. Die entstandenen Probleme werden dabei erläutert und die damit verbunden Lösungsansätze vorgestellt. Der gesamte Quellcode wurde auf Github1 veröffentlicht.

5.1 Entwicklungsumgebung und Buildtools
Für die Entwicklung von Scala- und im speziellen für Lift-Anwendungen besteht grundsätzlich die Möglichkeit einen herkömmlichen Editor wie Vim oder Notepad in Verbindung mit einem Buildtool zu nutzen. Für eine etwas komfortablere Entwicklung stehen für die meist genutzten Entwicklungsumgebungen wie Eclipse, NetBeans oder IntelliJ entsprechende Scala-Plugins zu Verfügung [CBDW11, S. 6 f.]. Im Laufe der PlanningWeb-Entwicklung kam IntelliJ 2 und das Build-Tool SBT 3 zum Einsatz.

5.1.1 IntelliJ
IntelliJ IDEA wurde in der Community Edition 10.0.3 mit Scala-Plugin verwendet, das sich über den Plugin Manager installieren lässt. Zu den wichtigsten Funktionen des Plugins zählt Code Highlighting und Code Completion. Darüber hinaus kann mit Projekten gearbeitet werden, die sowohl Scala als auch Java Dateien enthalten. Weiter wird das Compilieren, Testen und Refaktorisieren unterstützt. Die Entwicklungsumgebung bietet außerdem eine Unterstützung für Versionsverwaltungen wie SVC, Git, Mercural und Subversion an. Grundsätzlich lässt sich die Entwicklungsumgebung intuitiv und benutzerfreundlich bedienen. Allerdings fällt negativ auf, dass die Reaktionszeit von IntelliJ nach mehreren Stunden sehr stark ansteigt, so das ein Neustart erforderlich wird. Um die generelle Reaktionszeit von IntelliJ zu verbessern, kann die Datei idea.vmoptions im bin Verzeichnis wie in Listing 5.1 gezeigt angepasst werden.
1 2

https://github.com/spirit-fhs/planningweb http://www.jetbrains.com/idea/ 3 http://code.google.com/p/simple-build-tool/

Christoph Schmidt

Seite 29 von 49

5. Implementierung

Fachhochschule Schmalkalden SS 2011

Listing 5.1: Modifizierte Datei idea.vmoptions -Xms512m -Xmx2048m -XX:MaxPermSize=512m -XX:ReservedCodeCacheSize=64m -ea Auch das Refaktorisieren bereitet Probleme. Das Umbenennen von Methoden oder Klassen erzielte oft nicht den erwünschten Effekt, so dass per Hand eingegriffen werden musste. Ein weitere Schwachpunkt liegt im Verschieben von Dateien oder Paketen. Abschließend kann die Arbeit mit IntelliJ aber als positiv bewertet werden.

5.1.2 Simple-Build-Tool
Zum Übersetzten des Projekts kam SBT 0.7.4 zum Einsatz. Dahinter verbirgt sich ein Kommandozeilenprogramm das Scala Projekt übersetzt. Es setzt Java 1.5 oder eine aktuellere Version voraus. Projekte werden mit der Sprache Scala konfiguriert. Es ist auch möglich den Funktionsumfang von SBT mit Hilfe von entsprechenden Scala-Plugins zu erweitern. Außerdem unterstützt das Programm das Testen von Anwendungen, da es die Test-Frameworks Scala-Check, Specs und ScalaTest unterstützt. Für das Arbeiten mit webbasierten Anwendungen stellt SBT einen integrierten Jetty-Server für Testzwecke bereit, dessen Bedienung in Listing 5.2 dargestellt ist. Listing 5.2: Benutzung des Simple-Build-Tools ~/planningweb$ sbt [info] Building project sprit_planningweb_cs 0.1 against Scala 2.8.1 [info] using LiftProject with sbt 0.7.4 and Scala 2.7.7 >jetty-run [info] [info] == copy-resources == [info] == copy-resources == [info] [info] == compile == ... Im Projektverzeichnis der Applikation wird sbt mit dem Aufruf sbt gestartet. Anschließend folgt die Eingabe von jetty-run, was die Anwendung übersetzt und startet. Sofern der Quellcode fehlerfrei übersetzt wurde, kann das Programm mit einem Browseraufruf von http://localhost:8081 gestartet werden. Beim erstmaligen Ausführen sollte allerdings nach dem Start von SBT ein update Befehl ausgeführt werden, um Paketabhänigkeiten aufzulösen. Alternativ kann dem jetty-run Befehl eine Tilde vorangestellt werden. Dadurch wird das Projekt automatisch bei Änderungen am Quellcode neu übersetzt. Mit dem Aufruf der Befehlsfolge sbt clean update compile prepare-webapp package erzeugt SBT eine war-Datei, die dann auf einem Application-Server ausgeführt werden kann.

Christoph Schmidt

Seite 30 von 49

5. Implementierung

Fachhochschule Schmalkalden SS 2011

5.2 Menü und Zugriffskontrolle
Wie in Kapitel 2.2.5 erläutert verfügt Lift bereits über eine Benutzerverwaltung und Menüsteuerung. Allerdings soll die Authentifizierung an der PlanningWebAbbildung 5.1: PlanningWeb-Anmeldung

Anwendung mit Hilfe der FH-internen LDAP-Server durchgeführt werden. Das Framework beinhaltet im Paket net.liftweb.ldap ein LDAP-Modul. Dieses kann aber auf Grund der FH-internen Struktur nicht zum Einsatz kommen. Für die Abfrage aller relevanten Daten muss auf zwei unterschiedliche LDAP-Server zugegriffen werden, welche die relevanten Daten vorhalten. Das enthaltene Modul kann lediglich Daten von einem LDAP-Server abfragen. Aus diesem Grund wurde in einer anderen Arbeit des Spirit-Projekts ein Fhs-LDAP-Modul entwickelt, das auch in dieser Anwendung Verwendung findet. Der Quellcode wurde auf Github4 veröffentlicht.

5.2.1 FhS-LDAP-Module
Um zu ermöglichen, dass sich Dozenten am System mit ihrer FHS-ID anmelden können, wird im Objekt User des Moduls die Methode loginXhtml aus dem abgeleiteten Trait MetaMegaProtoUser überschrieben, welcher im Paket net.liftweb.mapper enthalten ist. Diese Methode repräsentiert das Standard-Anmeldeformular. Listing 5.3: Die Methode loginXhtml override def loginXhtml = { (<lift:surround with="default" at ="content"> <h3>{"Login nur mit gültiger FHS-ID möglich!"}</h3> <form method="post" action={S.uri} name="login"> <table> <tr><td colspan="2">{S.??("log.in")}</td></tr> <tr><td>{S.??("FHS-ID")}</td><td><user:user /></td></tr>
4

https://github.com/mdenison/FhS-LDAP-Module

Christoph Schmidt

Seite 31 von 49

5. Implementierung

Fachhochschule Schmalkalden SS 2011

<tr><td>{S.??("password")}</td><td><user:password /></td></tr> <tr><td><user:submit /></td></tr> </table> </form> <script type="text/javascript" language="JavaScript"> document.forms[’login’].elements[’username’].focus(); </script> </lift:surround>) } Der Trait MetaMegaProtoUser definiert darüber hinaus einen User und bietet eine Methode currentUserId an. Diese Methode liefert nach erfolgreicher Anmeldung die FHS-ID eines Dozenten zurück. Dadurch wird es möglich eine Rollenunterscheidung der einzelnen Benutzergruppen zu implementieren. Hierzu ist in der Datei Boot.scala der Applikation eine Methode is implementiert, wie in Listing 5.4 dargestellt. Listing 5.4: Die Methode is def is(user: String): Boolean = { Props.get(user, "") .split(";") .contains(User.currentUserId.openOr("")) } Die Methode bekommt bei Aufruf einen Suchstring übergeben und prüft in der Konfigurationsdatei default.props ob der Benutzer der gesuchten Benutzergruppe entspricht. Die is Methode wird von den Methoden isSuperUser, isCourseSheduler und isTimetableSheduler aufgerufen, um eine bessere Lesbarkeit des Quellcodes zu erziehlen, wie in Listing 5.5 zu sehen ist. Listing 5.5: Die Methode isTimetableSheduler def isTimetableSheduler : Boolean = { is("spirit.timetable.user") }

5.2.2 SiteMap
Das Menü der Anwendung wird in der Methode sitemap erstellt. Um eine Unterscheidung zwischen den vier Benutzergruppen zu erzielen enthält die Klasse Boot in der Methode boot die Attribute: • ifSuperUser • ifDozent • ifCourseSheduler • ifTimetableSheduler.

Christoph Schmidt

Seite 32 von 49

5. Implementierung

Fachhochschule Schmalkalden SS 2011

Listing 5.6: Attribut ifTimetableSheduler val ifTimetableSheduler = If (() => if (isTimetableSheduler || isSuperUser) {true} else {false}, () => RedirectResponse("/index")) Listing 5.6 stellt exemplarisch das Attribut ifTimetableSheduler dar. Bei diesem Attribut handelt es sich um einen sogenannten LocParam, auf den im weiteren Verlauf noch genauer eingegangen wird. Alle Elemente zum Erstellen einer SiteMap sind im Paket net.liftweb.sitemap enthalten. Die bereits angesprochene Methode sitemap liefert ein Objekt der Klasse SiteMap zurück. Diese bekommt die einzelnen Menüeinträge im Konstruktor übergeben. Listing 5.7: Auszug der Methode sitemap def sitemap = SiteMap( /*...*/ Menu.i("Raumverwaltung") / "room" / "management" >> ifTimetableSheduler /*...*/ ) Listing 5.7 zeigt beispielhaft den Menüeintrag der Raumverwaltung. Mit Hilfe der im Objekt Menu enthaltenen Methode i wird ein Eintrag für die Raumverwaltung erzeugt. Zu diesem Eintrag wird mit der “/” Methode der Pfad zur Website hinzugefügt, die die Raumverwaltung repräsentiert. Die “»” Methode fügt dem Menüeintrag noch den LocParam ifTimetableSheduler hinzu. Dieser ist ein Objekt der Klasse If. Der erste Parameter dieser Klasse ist eine Funktion, die prüft ob der Zugriff auf die entsprechende Seite erlaubt ist oder nicht. Der zweite Parameter repräsentiert die Rückgabe an den Browser im Fehlerfall. Im Falle der Raumverwaltung würde der Benutzer bei einem Fehler auf die Start-Seite umgeleitet werden. Sollte der Zugriff auf die Seite nicht erlaubt sein, wird der Menüeintrag nicht in der SiteMap angezeigt.

5.3 Persistenz und Transformation
Wie bereits in Kapitel 4.4.1 erläutert, wurde in der PlanningWeb-Anwendung eine Persistenz-Komponente implementiert. Dies wurde nötig, da das gesamte System datenbankunabhänig umgesetzt werden sollte. Die persistence Komponente setzt sich aus einem Trait IPersistence, welcher als Schnittstelle fungiert, der konkreten Implementierung Persistence und dem Objekt PersistenceFactory zusammen. Listing 5.8: Der Trait IPersistence trait IPersistence { def read : List[AnyRef]

Christoph Schmidt

Seite 33 von 49

5. Implementierung

Fachhochschule Schmalkalden SS 2011

def create(obj: AnyRef) def delete(obj: AnyRef) def update(before: AnyRef, after: AnyRef) } Bei Betrachtung von Listing 5.8 fällt der Typ AnyRef auf. Dieser Typ ist ein Subtyp der Wurzelklasse Any. AnyRef ist die Basisklasse aller Referenzklassen in Scala. Diese Klasse ist als Alias von java.lang.Object zu sehen [OSV10, S. 212 ff.]. Dadurch wird es möglich die im Trait IPersistence definierten Methoden für unterschiedliche Objekte nutzbar zu machen. Das Objekt PersistenceFactory ist als Singelton-Objekt implementiert. Scala unterstützt im Gegensatz zu Java die Möglichkeit Singelton-Objekte zu erzeugen. Dazu wird lediglich bei der Definition eines solchen Objektes statt dem Schlüsselwort class das Schlüsselwort object verwendet [OSV10, S. 65], wie in Listing 5.9 zusehen. Listing 5.9: Das Objekt PersistenceFactory object PersistenceFactory { def createPersistence (transform: ITransform) : IPersistence = { new Persistence(transform) } } Das Objekt PersistenceFactory verfügt lediglich über eine Fabrikmethode mit dem Namen createPersistence, bei deren Aufruf ein konkretes Objekt der Schnittstelle ITransform als Parameter mit übergeben wird. Als Ergebnis liefert diese Methode dann ein entsprechendes Persistenz-Objekt zurück. Die Schnittstelle ITransform ist für die Konvertierung eines konkreten Datenbankobjektes in ein Anwendungsobjekt zuständig. Die Komponente transform verfügt wiederum über ein Fabrikobjekt, welches für jedes persistente Objekt ein entsprechendes Transformationsobjekt erzeugt. Listing 5.10: Das Objekt TransformFactory object TransformFactory { def createTransformDozentType(persType: String) : ITransform = { persType match { case "mongoDB" => new TransformDozentTypeMongo case _ => error("Could not support: " + persType) } } /*...*/ } Listing 5.10 zeigt beispielhaft die Methode createTransformDozentType des Objektes TransformFactory. Dieser Methode wird der zugrunde liegende Datenbanktyp übergeben, der in der Datei default.probs definiert ist. Auf diese Art und Weise wird es möglich unterschiedliche Datenbanken zu unterstützen. Diese Implementierung bietet den Vorteil, dass bereits bestehender Quellcode nur noch an zwei Stellen

Christoph Schmidt

Seite 34 von 49

5. Implementierung

Fachhochschule Schmalkalden SS 2011

des Programms verändert werden muss, nämlich das Objekt TransformFactory und die Datei Boot.scala, um weiter Datenbanken zu unterstützen. Alle neuen Transformationsklassen kommen lediglich ergänzend hinzu. Listing 5.11: Anlegen eines Persistenz-Objektes val persistence:IPersistence = PersistenceFactory.createPersistence(TransformFactory. createTransformDozentType(persLayer)) val dozentTypes = persistence.read.asInstanceOf[List[DozentType]] Listing 5.11 zeigt wie ein Persistenz-Objekt in der Anwendung angelegt werden kann. Dieses bietet dann die entsprechenden Methoden um Objekte aus der Datenbank zu lesen, zu schreiben, zu löschen und zu verändern. Das Beispiel zeigt auch, dass beim Lesen von Objekten aus der Datenbank das Ergebnis der read Methode explizit mit dem Aufruf von asInstanceOf in den erwarteten Rückgabetyp umgewandelt werden muss. Der Versuch den Aufruf von asInsatnceOf mittels Implicit conversions 5 überflüssig zu machen schlug fehl, da beispielsweise die Klassen Dozent und DozentType im Paket Dozentmanagement beide ein Attribut name besitzen, was dazu führt, dass es mehrere Möglichkeiten zur impliziten Umwandlung gibt. Abschließend soll darauf hingewiesen werden, dass Lift mit dem Record-Framework den Ansatz verfolgt Datenbankzugriffslogik in Anwendungsobjekten unterzubringen. Durch die hier dargestellte Trennung zwischen Anwendungs- und Datenbankobjekten kann der volle Umfang der Lift-Records nicht in der Anwendung genutzt werden.

5.4 Lehrveranstaltungsverwaltung und Planung
Alle relevanten Dateien der Lehrveranstaltungsverwaltung und Planung befinden sich in der snippet Komponente unter lectures.snippet. Bei Betrachtung der einzelnen Menüs fällt auf, dass sich beispielsweise das Erstellen einer Lehrveranstaltung über mehrere Seiten erstreckt. Für solche Formulare bietet Lift so genannte Screens und Wizards an, welche im Packet net.liftweb.wizard enthalten sind [Pol11b, S. 37 f.]. Beim Versuch, diese auch in der PlanningWeb-Anwendung einzusetzen, stellte sich allerdings heraus, dass diese für die dortigen Zwecke ungeeignet sind. Abbildung 5.2: Lehrveranstaltung erfassen: Seite 1

5

Weiterführende Informationen zu Implicit conversions sind in [OSV10, S. 112 f.] zu finden.

Christoph Schmidt

Seite 35 von 49

5. Implementierung

Fachhochschule Schmalkalden SS 2011

Beim Erfassen der Lehrveranstaltungen ist es notwendig nach der Vergabe eines Namens und der Typauswahl eine Menge von Studiengängen zu selektieren. Abbildung 5.3: Lehrveranstaltung erfassen: Seite 2

Anschließend soll aus den Studiengängen eine Formularseite generiert werden, auf der die einzelnen Semester zu den entsprechenden Studiengängen ausgewählt werden können. Abbildung 5.4: Lehrveranstaltung erfassen: Seite 3

Dies ließ sich jedoch nicht mit den Wizards umsetzen, da diese nicht für dynamisch generierte Formulare geeignet sind. Der Vorgang des Erstellens einer Lehrveranstaltung ist dem Änderungsvorgang sehr ähnlich. Deshalb wurde versucht den Algorithmus für beide Vorgänge nutzbar zu machen, um Quellcoderedundanzen zu verhindern. Für diese Zwecke bietet sich das Template Method-Muster an, was im folgenden Abschnitt kurz vorgestellt wird.

5.4.1 Template Method-Muster
Das Template Method-Muster definiert das Grundgerüst eines Algorithmusses in einer Methode und überlässt einige Teile den Unterklassen. Dieses Muster lässt Unterklassen die Freiheit bestimmte Schritte zu redefinieren, ohne dabei die Struktur des Algorithmuses zu verändern [GHV98, S. 274]. Diese Muster eignet sich in folgenden Situationen: • Um unveränderliche Teile eines Algorithmusses einmal zu implementieren und es Unterklassen zu überlassen, das variierende Verhalten zu implementieren [GHV98, S. 275].

Christoph Schmidt

Seite 36 von 49

5. Implementierung

Fachhochschule Schmalkalden SS 2011

• Wenn gemeinsames Verhalten zwischen Unterklassen erkannt wurde, das aus diesen herausgelöst werden soll. Das Verhalten wird dann in eine gemeinsame Klasse verlagert um redundanten Quellcode zu vermeiden [GHV98, S. 274].

5.4.2 Umsetzung des Template Method-Musters
Wie bereits angesprochen ist das Erstellen einer Lehrveranstaltung dem Ändern einer solchen sehr ähnlich. Deshalb wurden diese Vorgänge mittels des Template Method-Musters umgesetzt. • Der Trait LecturesCreateNavigator definiert die Template-Methode namens navigation. • Die Klasse LecturesCreate repräsentiert das Menü zum Erstellen einer Lehrveranstaltung und benutzt hierzu die Basisimplementierung der TemplateMethode. • Die Klasse LecturesUpdate repräsentiert das Menü zum Ändern einer Lehrveranstaltung. Listing 5.12: Die Template-Methode des Traits LecturesCreateNavigator def navigation = { Status.is match { case LecturesCreateHelper.InitialStatus => addName case LecturesCreateHelper.AddedName => addCourses case LecturesCreateHelper.AddedCourse => addSemesters case LecturesCreateHelper.AddedSemester => addDozents case LecturesCreateHelper.AddedDozent => addHoures case LecturesCreateHelper.AddedHoure => saveLecture } } Listing 5.12 stellt die Template-Methode dar, welche den Erstellungs- bzw. Änderungsprozess steuert. Das Objekt Status repräsentiert eine Sessionvariable, in der der aktuell bearbeitete Status des Vorgangs gespeichert wird. Die einzelnen Zustände in denen sich das Status-Objekt befinden kann, werden durch das LecturesCreateHelper-Objekt definiert. Durch das von Scala unterstützte Pattern-Matching kann so zwischen den einzelnen Menu-Seiten mittels Weiter- und Zurück-Button navigiert werden. Die Add-Methoden wie addName oder addCourse generieren dabei dynamisch die entsprechenden Formular-Seiten.

5.4.3 Planungsprozess
Der Planungsprozess ist der Kern des Systems. Er ist dafür verantwortlich aus den zuvor erfassten Lehrveranstaltungen konkrete Veranstaltungen einer Studienwoche des entsprechenden Semesters zu generieren. Diese Daten bilden die Grundlage für

Christoph Schmidt

Seite 37 von 49

5. Implementierung

Fachhochschule Schmalkalden SS 2011

den Stundenplanungsprozess. Für diese Zwecke wurde das Objekt PlanningLectureCreater implementiert. Es bietet eine Methode buildPlan an, die eine Liste von Lehrveranstaltungen, wie in Abbildung 4.4 eingeführt, als Argument übergeben bekommt und daraus eine Liste von PlanningLectures erstellt, die alle stundenplanungsrelevanten Daten beinhaltet. Listing 5.13: Die Methode buildPlan def buildPlan(lectures: List[Lecture]): List[PlanningLecture] = { lectures.map(buildPlanningLecture(_)).flatten } Listing 5.13 zeigt die Implementierung der zuvor angesprochenen Generierungsmethode. Das Beispiel stellt dar, wie mit hilfe der map Methode auf jedes Element der Liste die Funktion buildPlanningLecture angewendet wird. Diese Methode verrichtet die eigentliche Arbeit und generiert eine Liste vom Typ PlanningLecture. Das wiederum hat zur Folge, dass eine verschachtelte Ergebnisliste entsteht. Deshalb wird auf das Ergebnis die flatten Methode angewendet um die Ergebnisliste zu glätten. Der Aufbau eines PlanningLecture Objektes ist in Listing 5.14 dargestellt. Listing 5.14: Die Klasse PlanningLecture case class PlanningLecture(name: String, typeOfLecture: String, groups: List[CourseSemester], dozents: List[Dozent], numberOfMembers: Int) Im weiteren Verlauf soll nun die Methode buildPlanningLecture genauer analysiert werden, wie in Listing 5.15 dargestellt. Listing 5.15: Die Methode buildPlanningLecture def buildPlanningLecture(lecture: Lecture): List[PlanningLecture] = { val minHouresOfLecture = 1 val maxHouresOfLecture = lecture.hoursOfLecture val minHouresOfTutorial = 1 val maxHouresOfTutorial = lecture.hoursOfTutorial val rangeHouresOfLecture = (minHouresOfLecture to maxHouresOfLecture).toList val rangeHouresOfTutorial = (minHouresOfTutorial to maxHouresOfTutorial).toList val lectureType = "Vorlesung" val tutorialType = "Übung" /*...*/ if(lecture.hasLectureTogetherWith.isEmpty && lecture.hasTutorialTogetherWith.isEmpty) { buildPlanningLectureWithEmptyListsForHasLATTogetherWith

Christoph Schmidt

Seite 38 von 49

5. Implementierung

Fachhochschule Schmalkalden SS 2011

} else { buildPlanningLectureWithNoEmptyListsForHasLATTogetherWith } } Diese Methode unterscheidet, ob für eine Lehrveranstaltung Übungs- bzw. Vorlesungsgruppen erstellt wurden oder nicht und ruft dementsprechend eine der beiden Methoden • buildPlanningLectureWithEmptyListsForHasLATTogetherWith6 • buildPlanningLectureWithNoEmptyListsForHasLATTogetherWith7 auf. Diese beiden Methoden berechnen die Veranstaltungen, welche im Laufe einer Woche angeboten werden müssen und geben diese als Liste von PlanninLectures zurück. Listing 5.16 stellt eine der beiden Methoden dar. Listing 5.16: buildPlanningLectureWithNoEmptyListsForHasLATTogetherWith def buildPlanningLectureWithNoEmptyListsForHasLATTogetherWith = { def getCourseInfosFrom(lecture: Lecture, courseSemesters: List[ CourseSemester]) = { lecture.courseInfos .filter(ci => courseSemesters .exists(_.course == ci.course.name)) } val lecturesToPlan = lecture .hasLectureTogetherWith .map(lr => PlanningLecture(lecture.name, lectureType, lr.these, lr.withThose, calculateNumberOfMembers(getCourseInfosFrom(lecture, lr.these)))) val lectureList = rangeHouresOfLecture .map(nr => lecturesToPlan).flatten val tutorialsToPlan = lecture .hasTutorialTogetherWith .map(lr => PlanningLecture(lecture.name, tutorialType, lr.these, lr.withThose,
6 7

Der Methodenname wurde abgekürzt. “...LAT...” steht für “...LectureAndTutorial...”. Der Methodenname wurde abgekürzt. “...LAT...” steht für “...LectureAndTutorial...”.

Christoph Schmidt

Seite 39 von 49

5. Implementierung

Fachhochschule Schmalkalden SS 2011

calculateNumberOfMembers(getCourseInfosFrom(lecture,lr. these)))) val tutorialList = rangeHouresOfTutorial .map(nr => tutorialsToPlan).flatten lectureList union tutorialList } Diese Methode berechnet jeweils für Vorlesungen und Übungen getrennte Listen welche am Ende mittels union zu einer gemeinsamen Rückgabeliste vereint werden. Die so entstandenen Daten sollen dem Stundenplanungsprogramm als Grundlage dienen. Da das neue Stundenplanungsprogramm 8 bislang nur prototypisch implementiert wurde, können die mit der PlanningWeb-Anwendung generierten Daten bislang nicht für die Stundenplanung eingesetzt werden. Auch der Versuch die auf Basis dieser Arbeit generierten Daten für das alte Stundenplanungsmodul einzusetzen ist nicht möglich, da das den zeitlichen Rahmen der Arbeit weit überschreitet. Außderdem würde dadurch die in den Daten enthaltene Semantik teilweise verloren gehen. Mit diesem Programm ist es beispielsweise nicht möglich abzubilden, dass mehr als ein Dozent an einer Lehrveranstaltung beteiligt ist. Deshalb wurde für das Semesterplanungsmenü nur eine Dummy-Implementierung umgesetzt.

5.5 Arbeitszeitverwaltung
Die Verwaltung der Arbeitszeiten einzelner Dozenten umfasst eine weitere wichtige Aufgabe der PlanningWeb-Anwendung, da diese für den Stundenplanungsprozess von essentieller Bedeutung sind. Die Arbeitszeitverwaltung setzt sich aus einem Menü für die Dozenten zusammen, in dem sie via Radio-Buttons in einem Stundenplan ihre Wunscharbeitszeiten eintragen können. Raumwünsche können derzeit lediglich über ein Kommentarfeld eingetragen werden, wie in Abbildung 5.5 dargestellt. Weiter verfügt die Verwaltung über einen Bereich für den Stundenplaner, indem er die Arbeitszeitenerfassung für Dozenten freischalten kann. Darüber hinaus besteht für ihn die Möglichkeit, sich die Arbeitszeiten grafisch in einem Stundenplan anzeigen zu lassen, was Abbildung 5.6 zeigt. Das Menü bietet dem Stundenplaner auch die Möglichkeit die Arbeitszeiten aller Dozenten zu bearbeiten. Die dafür notwendigen Dateien befinden sich in der snippet Komponente unter worktimes.snippet. Das Menü zur Erfassung der Arbeitszeiten durch die Dozenten und das Menü des Stundenplaners zum Bearbeiten der Arbeitszeiten einzelner Dozenten basiert auf dem gleichen Prinzip. Deshalb wurde versucht eine Basisimplementierung für beide Menüs zu schaffen um redundanten Quellcode zu vermeiden. Der Unterschied zwischen den beiden Menüs besteht darin, dass Dozenten, welche sich am System authentifiziert haben, beim Aufruf des Menüeintrags Wunschzeiten
8

https://github.com/spirit-fhs/core

Christoph Schmidt

Seite 40 von 49

5. Implementierung

Fachhochschule Schmalkalden SS 2011

Abbildung 5.5: Stundenplan der Wunschzeitenerfassung

Abbildung 5.6: Menü Arbeitszeiten eines Dozenten anzeigen

Christoph Schmidt

Seite 41 von 49

5. Implementierung

Fachhochschule Schmalkalden SS 2011

direkt auf die Seite mit ihren Arbeitszeiten und Raumwünschen gelangen. Im Gegensatz dazu muss der Stundenplaner eine Möglichkeit besitzen, einen bestimmten Dozenten auszuwählen, um dessen Arbeitszeiten bearbeiten zu können. Um dies realisieren zu können, wurde die Klasse Wishtimes implementiert, welche das Menü für einen Dozenten darstellt. Das Menü für den Stundenplaner ist von dieser Klasse abgeleitet und in der Klasse WishtimesAdmin umgesetzt. Der Stundenplaner muss die Möglichkeit besitzen Arbeitszeiten zu verändern, auch wenn die Arbeitszeiterfassung für die Dozenten gesperrt ist. Das Menü wird mit Hilfe der status Variable freigeschaltet. Deshalb muss dieser Wert in der Klasse WorktimesAdmin auf true gesetzt werden. Darüber hinaus ist es auch nötig die Werte • isFHSDozent • worktimeOfDozent • noteTextOfDozent neu zu setzen, deren Basisimplementierung im Trait WishtimesHelper zu finden ist. Stellt man die beiden Wertzuweisungen für isFHSDozent gegenüber, wie in Listing 5.17 dargestellt, wird der Unterschied offensichtlich. Listing 5.17: Gegenüberstellung der Wertzuweisung für isFHSDozent /* isFHSDozent in WorktimesHelper.scala */ var isFHSDozent = fhsdozents.filter(_.fhsId == currentUserId) /* isFHSDozent in WorktimesAdmin.scala */ isFHSDozent = fhsdozents.filter(_.fhsId == FHSDozentName.is) Ruft ein Dozent das Menü Wunschzeiten auf, ist seine FHS-ID bereits beim Instanzieren der Klasse Wishtimes durch den Wert currentUserId bekannt. Das hat zur Folge, dass an dieser Stelle bereits die Arbeitszeiten und Raumnotizen berechnet werden können, um mit diesen die Darstellung des Stundenplans zur Auswahl der Arbeitszeiten zu berechen, welcher im Trait WishtimesTimetable durch den Wert timetable dargestellt ist. Im Gegensatz dazu ist die FHS-ID im Menü des Stundenplaners erst nach Auswahl eines Dozenten aus einem Drop-Down Menü bekannt, woraufhin in der Methode edit der Klasse WishtimesAdmin ein Redirect ausgeführt wird. Das wiederum hat zur Folge, das eine neue Instanz der Klasse WishtimesAdmin erzeugt wird. Bei der Instanzierung wird allerdings zuerst der Wert für isFHSDozent aus dem Trait WishtimesHelper berechnet, auf dessen Basis dann der Wert timetable für die Darstellung des Stundenplans berechnet wird. Daraus ergibt sich, dass der Stundenplaner einen leeren Stundenplan für den ausgewählten Dozenten angezeigt bekommen würde, da die Neuzuweisung in der Klasse WishtimesAdmin nicht berücksichtigt wird. Die Auswertung von timetable muss also solange unterdrückt werden, bis der Stundenplan tatsächlich benötigt wird. So ist gewährleistet, dass dieser auf Basis des Wertes von isFHSDozent aus der Klasse WishtimesAdmin berechnet wird, der dann die entsprechende FHS-ID enthält.

Christoph Schmidt

Seite 42 von 49

5. Implementierung

Fachhochschule Schmalkalden SS 2011

Listing 5.18: Auszug der Methode timetable lazy val timetable = <table onclick="changeColor()" id="table-select"> <thead> <th></th> <th>{"Montag"}</th> <th>{"Dienstag"}</th> <th>{"Mittwoch"}</th> <th>{"Donnerstag"}</th> <th>{"Freitag"}</th> </thead> <tr> <th>{"08:15-09:45"}</th> <th>{makeRadio("Mo",1)}</th> <th>{makeRadio("Tu",1)}</th> <th>{makeRadio("We",1)}</th> <th>{makeRadio("Th",1)}</th> <th>{makeRadio("Fr",1)}</th> </tr> /*...*/ Scala bietet für solche Fälle die Möglichkeit der lazy evaluation. Standartmäßig werden die Felder in Scala beim Instanzieren einer Klasse ausgewertet, was dem Prinzip der eager evaluation entspricht. Werden Werte mit dem lazy Modifier gekennzeichnet, hat dies zur Folge, das diese Felder erst bei Bedarf ausgewertet werden [Bra10, S. 102], was Listing 5.18 illustrieren soll. Abschließend muss noch die vererbte render Methode in der Klasse WishtimesAdmin überschrieben werden, was in Listing 5.19 dargestellt ist. Listing 5.19: Überschreiben der Render-Methode override def render = { "#edit *" #> edit }

5.6 Testfälle
Für das Erstellen von Software gehören Testfälle zum guten Ton. Deshalb wurden auch für die PlanningWeb-Anwendung Testfälle erstellt. Im Scala-Umfeld haben sich zahlreiche Test-Frameworks etabliert. Im Rahmen des PlanningWebs wurde Specs 9 in der Version 1.6.6 eingesetzt. Specs wurde als Alternative zu JUnit 10 entwickelt, um Java- oder Scala-Projekte zu spezifizieren und zu testen [Ano10]. Dieses Framework eignet sich zum Erstellen und Überprüfen einer Spezifikation. Zuerst wird ein Objekt definiert, dass von der Klasse Specification abgeleitet ist [Bra10, S. 242], was das Listing 5.20 darstellt.
9 10

http://code.google.com/p/specs/ http://www.junit.org/

Christoph Schmidt

Seite 43 von 49

5. Implementierung

Fachhochschule Schmalkalden SS 2011

Listing 5.20: Das Objekt DozentManagementSpecs object DozentManagementSpecs extends Specification( "DozentManagement Specification") { /* ... */ } Anschließend wird die Spezifikation erstellt. Diese wird mittels should umgesetzt. Innerhalb der Spezifikation werden die Testfälle mit einer Zeichenkette, die den Test beschreibt und der Methode “»” implementiert [Bra10, S. 242 f.]. Listing 5.21 illustriert dieses Vorgehen anhand eines DozentType Objektes. Zuerst wird ein DozentType Objekt in der Datenbank gespeichert. Im Anschluss wird überprüft, ob das Erstellen erfolgreich war. Listing 5.21: Spezifikation des DozentType Objekt "DozentType" should { "when add a dozent-type" >> { val persistence:IPersistence = PersistenceFactory .createPersistence(TransformFactory .createTransformDozentType(usedPersistence)) persistence create(dozentType) "contain this dozent-type in persistence" >> { val dozentTypes = persistence.read.asInstanceOf[List[ DozentType]] dozentTypes contains(dozentType) must_== true } } /* ... */ } Alle Testfälle der PlanningWeb-Applikation sind im Verzeichnis src/test/scala zu finden.

Christoph Schmidt

Seite 44 von 49

6 Fazit und Ausblick
In der vorliegenden Arbeit wurde gezeigt, dass sich Scala/Lift sehr gut für die Entwicklung einer Anwendung zur Unterstützung der Lehr-/Stundenplanung eignet. Gerade durch die Konzepte der Sprache Scala konnten viele Probleme, die mit Mainstream-Sprachen nur schwer umzusetzen sind, auf elegante Art und Weise gelöst werden, was nicht zuletzt auf die Konzepte der funktionalen Programmierung zurückzuführen ist. Durch die rasante Weiterentwicklung der Sprache stellt sie schon jetzt eine echte Alternative zu Java oder vergleichbaren Sprachen darstellen. Auch die Erfahrungen, die mit dem Lift-Framework gemacht wurden, lassen darauf schließen, dass dieses Framework eine echte Chance auf dem kommerziellen Markt hat. Im Laufe der Ausarbeitung ist eine Software mit dem Namen PlanningWeb entstanden, welche die meisten der geforderten Anforderungen grundsätzlich erfüllt. Mit der Anwendung können alle geforderten Daten, die die Lehrplanung sowie die Unterstützung der Stundenplanung betreffen, erfasst und verwaltet werden. Nach Abschuss des Lehrplanungsprozesses ist es möglich konkrete Veranstaltungen zu generieren, welche in einer Studienwoche angeboten werden müssen. Allerdings können die generierten Daten noch nicht für den Stundenplanungsprozess genutzt werden, da es aus zeitlichen Gründen nicht gelungen ist, eine Schnittstelle für das alte Stundenplanungstool zu implementieren. Eine Schnittstelle für das neue Planungstool zu erstellen erwies sich als noch nicht sinnvoll, da dieses bislang nur prototypisch vorliegt. Eine Schnittstelle für das momentan eingesetzte Programm ist aktuell in Planung. Die Erfassung der Arbeitszeiten einzelner Dozenten konnte schon vor Ende dieser Arbeit fertiggestellt werden und wurde für die Planung des anstehenden Wintersemesters eingesetzt. Dabei war es auch möglich über ein Kommentarfeld Wunschräume zu reservieren. Allerdings hat der erste Durchlauf ergeben, dass das eingesetzte Formular Verbesserungspotential aufweist. Für den nächsten Durchlauf ist geplant das bisherige durch ein AJAX 1 -basiertes Formular auszutauschen. Die geforderte Datenbankunabhängigkeit kann zumindest theoretisch durch die Implementierung der beiden Komponenten Persistence und Transform bestätigt werden. Für die PlanningWeb-Anwendung wurden alle erforderlichen Klassen für den Einsatz einer MongoDB implementiert. Auf Grund des hohen Implementierungsaufwandes des gesamten Programms gelang es bislang nicht weitere Datenbanken zu testen. Bevor PlanningWeb aber endgültig das alte Lehrplanungstool ablösen kann, ist es erforderlich, eine Ansicht über die Arbeitszeitbelastung der Dozenten nachzureichen. Dies soll mit Hilfe der Google Chart API 2 realisiert werden. Für alle noch fehlenden Anforderungen ist geplant, diese bis Mitte des kommen1 2

Asynchronous JavaScript and XML http://code.google.com/intl/de-DE/apis/chart/

Christoph Schmidt

Seite 45 von 49

6. Fazit und Ausblick

Fachhochschule Schmalkalden SS 2011

den Semesters nachzureichen, um das veraltete Lehrplanungstool für die folgende Planung durch PlanningWeb zu ersetzen.

Christoph Schmidt

Seite 46 von 49

Literaturverzeichnis
[Ano10] Anonymous: User Guide: User guide for the specs framework. http://code.google.com/p/specs/wiki/UserGuide, Februar 2010. – 08.08.2011 [Ano11] Anonymous: Scala Team Wins ERC Grant. http://www.scala-lang.org/node/8579, Januar 2011. – 23.06.2011 [Bra10] Braun, Oliver: SCALA Objektfunktionale Programmierung. Carl Hanser Verlag, 2010 [CBDW11] Chen-Becker, Derek ; Danciu, Marius ; Weir, Tyler: Exploring Lift. http://exploring.liftweb.net/, Februar 2011. – 30.06.2011 [FRF+ 03] Fowler, Martin ; Rice, David ; Foemmel, Matthew ; Hieatt, Edward ; Mee, Robert ; Stafford, Randy: Patterns of Enterprise Application Architecture. Pearson Education, Inc., 2003 [GHV98] Gamma, Erich ; Helm, Richard ; Vlissides, John: Design Patterns CD: Elements of Reusable Object-Oriented Software. Addison-Wesley Longman, Inc., 1998 [Gre08] Greisle, Alexander: Tim Berners-Lee über das Internet. http://www.work-innovation.de/blog/2008/06/, Juni 2008. – 05.08.2011 [Hom02] Hommes, Werner: Objektorientierte Programmierung mit ABAP Objects. GRIN Verlag, 2002 [Mü05] Müller, Joachim: Workflow - based Integration. Springer, 2005 [OB09] Oestereich, Bernd ; Bremer, Stefan: Objektorientierte Softwareentwicklung: Analyse und Design mit UML 2.3. Oldenbourg Wissenschaftsverlag GmbH, 2009 (9. Auflage) [Ode08] Odersky, Martin: Scala’s Prehistory. http://www.scala-lang.org/node/239, August 2008. – 30.06.2011 [OSV10] Odersky, Martin ; Spoon, Lex ; Venners, Bill: Programming in Scala Second Edition. artima, 2010 [Per11] Perrett, Timothy: Lift IN ACTION: The simply functional web framework for Scala. Manning Publications Co., 2011

Christoph Schmidt

Seite 47 von 49

Literaturverzeichnis

Fachhochschule Schmalkalden SS 2011

[PH06] Pepper, Peter ; Hofstedt, Petra: Funktionale Programmierung: Sprachdesign und Programmiertechnik. Springer, 2006 [Pol11a] Pollak, David: Lift 2.3 Released. http://lift.la/lift-23-released, Mai 2011. – 23.06.2011 [Pol11b] Pollak, David: Simply Lift. http://simply.liftweb.net/Simply_Lift.pdf, 30.06.2011 Mai 2011. –

[Sem06] Semersheim, J.: Lightweight Directory Access Protocol (LDAP): The Protocol. Novell, Inc., 2006 [Sie04] Siedersleben, Johannes: Moderne Softwarearchitektur. dpunkt.verlag GmbH, 2004

Christoph Schmidt

Seite 48 von 49

Eidesstattliche Erklärung
Ich versichere an Eides statt durch meine eigenhändige Unterschrift, dass ich die vorliegende Arbeit selbstständig und ohne fremde Hilfe angefertigt habe. Alle Stellen, die wörtlich oder dem Sinn nach auf Publikationen oder Vorträgen anderer Autoren beruhen, sind als solche kenntlich gemacht. Ich versichere außerdem, dass ich keine andere als die angegebene Literatur verwendet habe. Diese Versicherung bezieht sich auch auf alle in der Arbeit enthaltenen Zeichnungen, Skizzen, bildlichen Darstellungen und dergleichen. Die Arbeit wurde bisher keiner anderen Prüfungsbehörde vorgelegt und auch noch nicht veröffentlicht.

Schmalkalden, den 09.08.2011

Christoph Schmidt

Christoph Schmidt

Seite 49 von 49