Diplomarbeit Entwicklung eines webbasierten

Werbung
Diplomarbeit
Entwicklung eines webbasierten
Zeiterfassungssystems mit vergleichender
Untersuchung von Datenbanktechniken
Eingereicht von Clemens Schweter
am Lehrstuhl Softwaretechnik
an der Technischen Universität Berlin
WS 2003/2004
1. Gutachter: Prof. Dr.-Ing. Stefan Jähnichen
2. Gutachter: Dr. Stephan Herrmann
Berlin, Mai 2004
i
Eidesstattliche Erklärung
Die selbstständige und eigenhändige Anfertigung versichere ich an Eides statt.
Berlin, den 27.05.2004
- Clemens Schweter Unterschrift
ii
Inhaltsverzeichnis
1 Motivation und Einleitung
1.1 Motivation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1.2 Die zu lösende Aufgabe . . . . . . . . . . . . . . . . . . . . . . . . . .
1.3 Vorgehensweise . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2 Requirements Engineering
2.1 Einleitung . . . . . . . . . . . . . . . . . . . . . . . . .
2.2 Definitionen . . . . . . . . . . . . . . . . . . . . . . . .
2.2.1 Was sind Requirements? . . . . . . . . . . . . .
2.2.2 Definition: Requirement . . . . . . . . . . . . .
2.2.3 Bedingungen an ein Requirement . . . . . . . .
2.2.4 Was ist Requirements Engineering? . . . . . . .
2.3 Das Requirements Document . . . . . . . . . . . . . .
2.3.1 Einleitung . . . . . . . . . . . . . . . . . . . . .
2.3.2 Requirements beschreiben . . . . . . . . . . . .
2.3.3 Systemmodellierung . . . . . . . . . . . . . . .
2.3.4 Struktur des Requirements Documents . . . . .
2.4 Anforderungen erheben (Elicitation) . . . . . . . . . .
2.4.1 Einleitung . . . . . . . . . . . . . . . . . . . . .
2.4.2 Erste Schritte . . . . . . . . . . . . . . . . . . .
2.4.3 System Stakeholder identifizieren und befragen .
2.4.4 Unterstützende Analysetechniken . . . . . . . .
2.5 Anforderungen analysieren und neu verhandeln . . . .
2.5.1 Anforderungen sprachlich überarbeiten . . . . .
2.5.2 Checklisten zur Überprüfung . . . . . . . . . . .
1
1
2
3
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
5
5
6
6
6
7
7
8
8
8
9
10
10
10
10
10
12
14
14
15
3 Analyse mit Requirements Engineering
3.1 Anforderungen erheben . . . . . . . . . . . . . . . . . . . . . . . . .
3.1.1 Erste Schritte . . . . . . . . . . . . . . . . . . . . . . . . . .
3.1.2 Analyse des Ist-Zustandes . . . . . . . . . . . . . . . . . . .
3.1.3 Befragung der Stakeholder mit verschiedenen Techniken . . .
3.1.4 Beschreibung der Stakeholder . . . . . . . . . . . . . . . . .
3.1.5 Unterstützende Analysetechniken . . . . . . . . . . . . . . .
3.2 Analyse der Anforderungen . . . . . . . . . . . . . . . . . . . . . .
3.2.1 Anforderungen sprachlich überarbeiten . . . . . . . . . . . .
3.2.2 Checklisten zur Überprüfung . . . . . . . . . . . . . . . . . .
3.3 Requirements Document . . . . . . . . . . . . . . . . . . . . . . . .
3.3.1 Systemmodelle . . . . . . . . . . . . . . . . . . . . . . . . .
3.3.2 Struktur eines Requirements . . . . . . . . . . . . . . . . . .
3.3.3 Struktur des Requirements Documents nach [IEEE830-1998]
3.4 Abschließende Worte zum Requirements Engineering . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
17
17
17
19
20
22
23
24
25
26
27
27
30
30
31
iii
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
4 Konzepte von ASP.NET
4.1 Grundlagen . . . . . . . . . . . . . .
4.1.1 3-Tier-Architektur . . . . . .
4.1.2 .NET - Framework . . . . . .
4.1.3 Businessobjekte . . . . . . . .
4.1.4 Die Programmiersprache C# .
4.1.5 ASP.NET Page-Framework .
4.2 Codebehind-Technologie . . . . . . .
4.3 Webforms . . . . . . . . . . . . . . .
4.3.1 Einleitung . . . . . . . . . . .
4.3.2 HTML Server Controls . . . .
4.3.3 Web Server Controls . . . . .
4.4 Zustandsmanagement . . . . . . . . .
4.5 Lebenszyklus eines Page-Objekts . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
5 Architektur und Entwurf der Webapplikation
5.1 Einleitung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5.2 Architektur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5.3 Persistenz-Framework . . . . . . . . . . . . . . . . . . . . . . . . . . .
5.3.1 Einleitung . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5.3.2 Persistenz Manager . . . . . . . . . . . . . . . . . . . . . . . .
5.3.3 Persistente Objekte . . . . . . . . . . . . . . . . . . . . . . . .
5.3.4 Die Klasse Controller . . . . . . . . . . . . . . . . . . . . . . .
5.3.5 Zusammenfassung und Übersicht über alle persistenten Objekte
5.4 Entwurf des Web-Interfaces . . . . . . . . . . . . . . . . . . . . . . .
5.4.1 Einleitung . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5.4.2 Struktur der GUI . . . . . . . . . . . . . . . . . . . . . . . . .
5.4.3 Problem bei Web-Applikationen . . . . . . . . . . . . . . . . .
5.4.4 Verwendung eines Datagrids . . . . . . . . . . . . . . . . . . .
5.4.5 Entwurf eines User Controls . . . . . . . . . . . . . . . . . . .
5.5 Zustandsmanagement . . . . . . . . . . . . . . . . . . . . . . . . . . .
5.5.1 PageNavigator . . . . . . . . . . . . . . . . . . . . . . . . . .
5.5.2 Start einer Session . . . . . . . . . . . . . . . . . . . . . . . .
5.6 Benutzerrechte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5.7 Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5.7.1 Gesamtstruktur . . . . . . . . . . . . . . . . . . . . . . . . . .
5.7.2 Beispielhafter Ablauf . . . . . . . . . . . . . . . . . . . . . . .
5.7.3 Schwierigkeiten beim Entwurf . . . . . . . . . . . . . . . . . .
5.7.4 Nebenläufigkeit . . . . . . . . . . . . . . . . . . . . . . . . . .
5.7.5 Übergang zur Implementierung . . . . . . . . . . . . . . . . .
iv
34
34
34
34
35
35
37
37
38
38
38
39
40
41
43
43
44
45
45
46
47
49
50
51
51
51
53
54
55
57
57
60
60
61
61
63
64
65
65
6 Implementierung mit relationaler Datenbank
6.1 Einleitung . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
6.2 Datendefinition . . . . . . . . . . . . . . . . . . . . . . . . . .
6.2.1 Datentypen und Domänen . . . . . . . . . . . . . . . .
6.2.2 Primärschlüssel . . . . . . . . . . . . . . . . . . . . . .
6.2.3 Fremdschlüsselverbindungen und referentielle Integrität
6.2.4 Integritätsbedingungen . . . . . . . . . . . . . . . . . .
6.2.5 Trigger . . . . . . . . . . . . . . . . . . . . . . . . . . .
6.2.6 Benutzerdefinierte Routinen . . . . . . . . . . . . . . .
6.2.7 Sichten (Views) . . . . . . . . . . . . . . . . . . . . . .
6.2.8 Schwächen der relationalen Datendefinition . . . . . . .
6.3 Datenmanipulation . . . . . . . . . . . . . . . . . . . . . . . .
6.3.1 Datenmanipulationsoperationen . . . . . . . . . . . . .
6.3.2 (SQL-)Transaktionen . . . . . . . . . . . . . . . . . . .
6.3.3 Nebenläufigkeitsanomalien . . . . . . . . . . . . . . . .
6.3.4 Nebenläufigkeitskontrolle . . . . . . . . . . . . . . . . .
6.4 Datenabfragen (Select) . . . . . . . . . . . . . . . . . . . . . .
6.4.1 Select-Statement . . . . . . . . . . . . . . . . . . . . .
6.4.2 Subqueries . . . . . . . . . . . . . . . . . . . . . . . . .
6.4.3 OUTER JOIN . . . . . . . . . . . . . . . . . . . . . .
6.5 Redundanzvermeidung durch Normalisierung . . . . . . . . . .
6.5.1 Begrifflichkeiten . . . . . . . . . . . . . . . . . . . . . .
6.5.2 1. Normalform . . . . . . . . . . . . . . . . . . . . . . .
6.5.3 2. Normalform . . . . . . . . . . . . . . . . . . . . . . .
6.5.4 3. Normalform . . . . . . . . . . . . . . . . . . . . . . .
6.5.5 Boyce-Codd-Normalform (BCNF) . . . . . . . . . . . .
6.6 ODBC-Schnittstelle . . . . . . . . . . . . . . . . . . . . . . . .
6.7 Konkrete Implementierung . . . . . . . . . . . . . . . . . . . .
6.7.1 Verwendete Modellierungstechnik . . . . . . . . . . . .
6.7.2 Entwurf des Datenmodells . . . . . . . . . . . . . . . .
6.7.3 (SQL-)Transaktionen . . . . . . . . . . . . . . . . . . .
6.7.4 Sichten . . . . . . . . . . . . . . . . . . . . . . . . . . .
6.7.5 Primärschlüssel und Identität . . . . . . . . . . . . . .
6.7.6 Referenzielle Integrität . . . . . . . . . . . . . . . . . .
6.8 Motivation zur Objektorientierung in Datenbanken . . . . . .
6.8.1 Vorteile einer relationalen Datenbank . . . . . . . . . .
6.8.2 Nachteile einer relationalen Datenbank . . . . . . . . .
6.8.3 Object-Oriented Database System Manifesto . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
67
67
68
68
68
69
69
70
70
71
71
71
71
72
72
73
74
74
76
77
78
78
79
80
81
82
82
83
83
84
87
89
90
91
92
92
93
95
7 Implementierung mit objektrelationaler Datenbank
7.1 Einleitung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
7.2 Erweiterte Datendefinition . . . . . . . . . . . . . . . . . . . . . . . .
7.2.1 Einleitung . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
98
98
99
99
v
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
7.3
7.4
7.5
7.6
7.2.2 Distinct-Typen . . . . . . . . . . . . . . . . . . . . . . .
7.2.3 Unbenannte Typkonstruktoren . . . . . . . . . . . . . . .
7.2.4 Strukturierte Typen . . . . . . . . . . . . . . . . . . . .
7.2.5 Typisierte Tabellen . . . . . . . . . . . . . . . . . . . . .
7.2.6 Typisierte Sichten . . . . . . . . . . . . . . . . . . . . . .
Erweiterte Datenabfragen und -manipulation . . . . . . . . . . .
Bewertung nach Datenbankmanifesto . . . . . . . . . . . . . . .
7.4.1 Komplexe Datentypen . . . . . . . . . . . . . . . . . . .
7.4.2 Objektidentität . . . . . . . . . . . . . . . . . . . . . . .
7.4.3 Kapselung . . . . . . . . . . . . . . . . . . . . . . . . . .
7.4.4 Typen- und Klassenhierarchien . . . . . . . . . . . . . .
7.4.5 Vererbung . . . . . . . . . . . . . . . . . . . . . . . . . .
7.4.6 Override, Overload und spätes Binden . . . . . . . . . .
7.4.7 Sprach- und Berechnungsvollständigkeit . . . . . . . . .
7.4.8 Erweiterbarkeit von Typen . . . . . . . . . . . . . . . . .
Klassenmodell in objektrelationales Datenmodell transformieren
Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . .
8 Vergleich: relationale und objektrelationale Datenbank
8.1 Relationale Datenbank . . . . . . . . . . . . . . . . . . .
8.1.1 Modellierungsmöglichkeiten und Normalisierung .
8.1.2 Definition von Primärschlüsseln . . . . . . . . . .
8.1.3 Integritätsbedingungen . . . . . . . . . . . . . . .
8.1.4 Abfragemöglichkeiten und Datenmanipulation . .
8.1.5 Nebenläufigkeit und Performanz . . . . . . . . . .
8.2 Verbesserungen durch eine objektrelationale Datenbank?
8.3 Vergleich objektrelational zu relational zusammengefasst
9 Zusammenfassung und Ausblick
9.1 Objektorientierte Datenbank . . . . . . . . . . .
9.2 Persistenz Framework und Datenbankvergleich .
9.3 Entwicklungsprozess . . . . . . . . . . . . . . .
9.4 Zusammenfassung der wichtigsten Erkenntnisse
9.5 Offene Frage . . . . . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
99
100
103
105
106
107
108
108
109
109
109
109
109
110
110
110
110
.
.
.
.
.
.
.
.
112
. 112
. 112
. 113
. 114
. 114
. 115
. 115
. 116
.
.
.
.
.
116
. 116
. 118
. 118
. 119
. 120
Literaturverzeichnis
122
A Requirements Document
126
vi
Abbildungsverzeichnis
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
Beispiel für eine Vergleichbarkeit von Fachgruppen . . . . . . . . . . .
Gliederung und Vorgehensweise . . . . . . . . . . . . . . . . . . . . .
Requirements Engineering Prozess [Som Saw 97, S. 113] . . . . . . . .
Erste Befragung des Auftraggebers . . . . . . . . . . . . . . . . . . .
Kommunikation zwischen den Stakeholdern . . . . . . . . . . . . . . .
Activity Diagram des Ist-Zustandes für die Berichtserstellung . . . . .
Zustände eines Projekts . . . . . . . . . . . . . . . . . . . . . . . . .
Systemmodell: Klassendiagramm . . . . . . . . . . . . . . . . . . . .
Statechart Diagramm für die Menüführung . . . . . . . . . . . . . . .
Use Case Modell zur Beschreibung der drei Hauptfunktionalitäten . .
Aufbau eines Requirements . . . . . . . . . . . . . . . . . . . . . . .
Requirement Dokument nach [IEEE830-1998] . . . . . . . . . . . . .
3-Tier-Architektur für Web-Applikationen . . . . . . . . . . . . . . .
Das .NET Framework . . . . . . . . . . . . . . . . . . . . . . . . . .
Beispiel für die Verwendung von Properties . . . . . . . . . . . . . . .
Beispielcode für die Verwendung eines Indexer . . . . . . . . . . . . .
Beschreibung der Codebehind-Technologie . . . . . . . . . . . . . . .
Zusammenhang von HTML und Server Controls . . . . . . . . . . . .
Lebenszykus eines Page-Objekts . . . . . . . . . . . . . . . . . . . . .
Struktur der Komponenten . . . . . . . . . . . . . . . . . . . . . . . .
Übersicht der spefizischen Komponenten . . . . . . . . . . . . . . . .
Struktur des Persistenz Frameworks am Beispiel Projekt . . . . . . .
Rollen des Factory Patterns im Persistenz-Framework . . . . . . . . .
Einfügen eines persistenten Objektes . . . . . . . . . . . . . . . . . .
Die Klasse Controller mit zwei Beispielmanagern . . . . . . . . . . . .
Klassendiagramm der persistenten Objekte . . . . . . . . . . . . . . .
Seitenaufbau der Default-Webform . . . . . . . . . . . . . . . . . . .
Die Webform Default und die Codebehind-Klasse PageFrontdoor . . .
Eigenschaften einer Web-Applikation . . . . . . . . . . . . . . . . . .
Beispielanwendung für ein Datagrid . . . . . . . . . . . . . . . . . . .
Beispiel für ein User Control . . . . . . . . . . . . . . . . . . . . . . .
Klasse DateControl . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Sequenz Diagramm zum DateControl am Beispiel Mitarbeitereingabemaske . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Beispielklasse des PageNavigators zur Steuerung der Benutzeroberfläche
Abhängig vom PageNavigator werden die jeweiligen Templates geladen
Beispiel für Zustandsänderung mit PageNavigator . . . . . . . . . . .
Sequenz Diagramm für das Starten einer Session . . . . . . . . . . . .
Zusammenfassende Darstellung am Beispiel Mitarbeiterverwaltung . .
Sequenz Diagramm bei einer Serveranfrage ohne Event . . . . . . . .
Sequenz Diagramm bei einer Serveranfrage durch ein Event . . . . . .
vii
3
3
5
11
18
19
20
28
29
29
32
33
34
35
36
36
38
39
42
44
45
46
47
48
49
51
52
53
54
54
55
56
56
58
58
59
60
62
63
63
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
Referenzielle Aktionen nach [Tür 03, S. 21] . . . . . . . . . . . . . . . 70
Die ACID-Eigenschaften, die eine Transaktion erfüllen sollte . . . . . 72
Anomalien bei nebenläufigen Transaktionen nach [FO 04b] . . . . . . 73
Einfache Darstellung des SQL-Select-Statements . . . . . . . . . . . . 75
Verbund von zwei SQL-Tabellen . . . . . . . . . . . . . . . . . . . . . 75
SQL-Select-Statement zu dem Beispielverbund von Abbildung 45 . . 75
Ad-hoc-Abfrage über alle Mitarbeiter in einem Projekt in einer ausgewählten Woche . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76
Definition einer Sicht auf Mitarbeiteraccounts . . . . . . . . . . . . . 76
Beispiel aus der Zeiterfassung für einen Subquery . . . . . . . . . . . 77
Beispiel für outer join . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
Verkürztes Ergebnis der Anfrage aus Abbildung 50 . . . . . . . . . . 78
Grafische Darstellung der 2NF . . . . . . . . . . . . . . . . . . . . . . 81
Grafische Darstellung der 3NF . . . . . . . . . . . . . . . . . . . . . . 81
Grafische Darstellung der BCNF . . . . . . . . . . . . . . . . . . . . . 82
Datenmodell nach der IDEF1X-Notation (siehe Kapitel 6.7.1) . . . . 85
Klasse Database . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88
Beispielanwendung für die Klasse Database ohne Ausnahmebehandlung 89
Sichten aus der Zeiterfassung . . . . . . . . . . . . . . . . . . . . . . 89
Screenshot: Eingabemaske der Vertragsmitarbeiter . . . . . . . . . . . 90
zusammengesetzter Primärschlüssel . . . . . . . . . . . . . . . . . . . 91
Beispiel für referenzielle Intrität zwischen Projekt und Projekttyp . . 92
Vorteile einer relationalen Datenbank . . . . . . . . . . . . . . . . . . 93
Nachteile eines relationalen Datenmodels anhand eines Beispiels . . . 94
Beispiel für Tupeltypkonstruktor . . . . . . . . . . . . . . . . . . . . . 100
Beispiel für Arraytypkonstruktor . . . . . . . . . . . . . . . . . . . . 101
Beispiel für eine SQL-Anfrage auf einem Array . . . . . . . . . . . . . 101
Beispiel für einen Referenztypkonstruktor . . . . . . . . . . . . . . . . 102
Beispiel für die Vorteile von Zugriffen über Referenzen . . . . . . . . 102
Beispiel für 1:n-Relation . . . . . . . . . . . . . . . . . . . . . . . . . 103
Merkmale eines strukturierten Typs (basiert auf [Eis+ 99]) . . . . . . 103
Aufbau eines strukturierten Typs . . . . . . . . . . . . . . . . . . . . 104
Vereinfachter Definitionsaufbau einer typisierten Tabelle . . . . . . . 106
Beispiel für eine typisierte Sicht . . . . . . . . . . . . . . . . . . . . . 107
Zwei Möglichkeiten für Vererbung im ER-Modell . . . . . . . . . . . . 113
Überblick relationale zu objektrelationaler Datenbank . . . . . . . . . 116
Beispiel für eine Implementierung mit objektorientierter Datenbank . 117
Auswirkung einer Anforderungsänderung (vgl. mit Kapitel 9.3) . . . . 121
viii
1
Motivation und Einleitung
1.1
Motivation
Obwohl die relationale Datenbank die mit Abstand am weitesten verbreitete Datenbanktechnik ist, hat diese doch viele Nachteile. In der Softwareentwicklung werden
objektorientierte Konzepte eingesetzt um Wiederverwendbarkeit durch Vererbung,
komplexe Datentypen, usw. zu verwenden und beim Modellieren der Datenbank wird
auf flache und einfache Tabellenstrukturen zurückgegriffen.
In dieser Arbeit werden die Möglichkeiten einer objektrelationale gegenüber einer
relationalen Datenbank verglichen. Grundlage für die objektrelationale Datenbank
ist der Standard SQL:19991 . Eine objektrelationale Datenbank ist eine Erweiterung
einer relationalen Datenbank und bietet Konzepte an, mit denen Objektorientierung
in einer Datenbank möglich ist.
Zuvor aber musste ein sehr konkretes Problem gelöst werden. Von der Firma
Francotyp Postalia wurde ich beauftragt im Rahmen einer Diplomarbeit ein webbasiertes Zeiterfassungssystem zu entwickeln. Das erste Problem, was sich dabei
stellte, war: Was soll das Zeiterfassungssystem können, also die Analyse? In vielen
Vorträgen zum Thema UML und anderen Modellierungstechniken wird sofort damit
begonnen, das Problem zu modellieren, aber woher kommen die Beschreibungen für
die zu lösenden Probleme? Vor allem, wenn es sich um ein Projekt in einer ”echten”
Firma handelt, sind die Anforderungen oft nicht von vornherein so klar. Durch Requirements Engineering soll genau diese Frage beantwortet werden: ”Was genau soll
entwickelt werden?”
Für die Entwicklung der Applikation wurde das .NET Framework verwendet. Eine der Komponenten dieses Frameworks ist ASP.NET. ASP.NET ist eine Technik,
mit der Web-Applikationen entworfen werden können, die ein etwas anderes Vorgehen besitzt, als es bei der Entwicklung von herkömmlichen Web-Applikationen der
Fall ist.
Ein weiterer Ansatz, um die Unterschiede zwischen objektorientierter Programmierung und relationaler Datenbank zu verringern, ist die Verwendung eines MappingTools, wie in [Scr+ 97] unter dem Begriff ”gateway-based object persistence” beschrieben ist. Bei einem Mapping-Tool wird eine automatische Umwandlung von
Klassenstrukturen zu relationalen Datenstrukturen vorgenommen. Basierend auf
diesem Konzept und der Struktur eines bereits existierenden Persistenz-Framework,
wurde eine Framework entworfen, was einen direkten Vergleich der Datenbanktechniken ermöglichen soll.
1
SQL:1999 ist der offizielle Namen und ist gleichbedeutend mit SQL-99 oder SQL-3.
1
Diese Struktur ermöglicht darüber hinaus nicht nur eine logischen, sondern auch
eine physikalische Trennung zwischen Entwurf und Implementierung. Das entwickelte Framework bildet dabei den Entwurf und die Komponente, die diese Framework
verwendet, und enthält (fast) nur noch Implementierungsaspekte.
Den Abschluss dieser Arbeit bildet ein Vergleich der relationalen und der objektrelationalen Datenbanktechnik, Schlussfolgerungen aus dem Entwicklungsprozess
und ein Ausblick, in dem die Verwendung einer objektorientierten Datenbank betrachtet wird.
1.2
Die zu lösende Aufgabe
Von der Firma Francotyp Postalia wurde eine Aufgabe gestellt, die, wie bereits
erwähnt wurde, im Rahmen einer Diplomarbeit gelöst werden sollte. Francotyp Postalia stellt Frankier- und Kuvertiermaschinen her. Für die Entwicklung einer neuen
Frankiermaschine2 sind u. a. folgende Schritte nötig, die von verschiedenen Teams
(im Folgenden Fachgruppe genannt) bearbeitet werden:
• Entwicklung und Weiterentwicklung der Hardware
• Entwicklung der eingebetteten Software
• Entwicklung der Mechanik
• Entwicklung und Weiterentwicklung von Tools zum Konfigurieren der Maschine
• Serverentwicklung zur Verwaltung der Kundendaten
Die Fachgruppen erledigen dabei unterschiedliche Tätigkeiten, die in einer abstrakten Form für alle Arten von Fachgruppen gleich sind. Bei einer Hardwareentwicklung muss, genauso wie bei einer Softwareentwicklung, analysiert, entworfen,
implementiert und getestet werden.
In langer und mühevoller Arbeit hat die Abteilung Hardware- und Softwareentwicklung, von der ich beauftragt wurde, einen solchen Katalog mit abstrakten
Aufgabenbeschreibungen (im Folgenden Aufgabenkatalog) erstellt. Diese Aufgabenkataloge sollen eine Vergleichbarkeit der unterschiedlichen Fachgruppen möglich machen. Abbildung 1 zeigt dies anhand eines Beispiels. Obwohl das Zusammenlöten
von Schaltungen scheinbar nichts mit der Programmierung einer Applikation zu tun
hat, kann es doch im Aufgabenkatalog Implementierung eine Vergleichbarkeit von
Hardware- und Softwareentwicklung ermöglichen.
2
Frankiermaschinen sind Maschinen, die einen der Briefmarke entsprechenden Aufdruck auf
einen Briefumschlag oder ein abziehbares Label drucken.
2
Aufgabenkatalog Fachgruppe Hardware
Analyse
20 %
Entwurf
30 %
Implementierung
50 %
Fachgruppe Software
30 %
60 %
10 %
Abbildung 1: Beispiel für eine Vergleichbarkeit von Fachgruppen
1.3
Vorgehensweise
Bei der Entwicklung der Applikation Zeiterfassung wurde, wie in Abbildung 2 dargestellt ist, vorgegangen.
Abbildung 2: Gliederung und Vorgehensweise
Der erste Schritt in einem Softwareentwicklungsprozess ist die Analyse. Requirements Engineering stellte Techniken, Methoden und Vorgehensweisen zur Verfügung,
zum Erheben, Analysieren und Beschreiben von Anforderungen. Durch eine systematische Vorgehensweise sollen Fehler in der Analyse vermieden werden. Im Kapitel
2 werden diese Konzepte vorgestellt. Das Kapitel 2 dient als Grundlage für die eigentliche Analyse bzw. Anforderungsermittlung, die in Kapitel 3 beschrieben wird.
Nach der Analyse folgt der Entwurf. Die zu erstellende Applikation sollte mit
dem ASP .NET Page-Framework entwickelt werden. Im Kapitel 4 wird diese Framework vorgestellt und auf einige Konzepte, die im Weiteren benötigt werden, genauer
eingehen. Prinzipiell sollte der Entwurf unabhängig von der Implementierung sein.
Es hat sich aber herausgestellt, dass dies für die Entwicklung in einem Framework
nicht so ohne weiteres möglich ist. Im Kapitel 5 wird, basierend auf den Konzepten
3
von Kapitel 4, der Entwurf für die Zeiterfassung mit ASP.NET beschrieben.
Um eine Vergleichbarkeit von verschiedenen Datenbanktechniken zu ermöglichen,
wurde ein Framework entwickelt. Die datenbankspezifischen Aspekte werden in eine
separate Komponente auslagert, die das entwickelte Framework verwendet. Damit
kann, abhängig von der verwendeten Datenbanktechnik, eine der spezifischen Komponenten verwendet und verglichen werden. Die konkrete Implementierung wurde
mit einer relationalen Datenbank durchgeführt.
Basierend auf dem entwickelten Framework von Kapitel 4, wird die eine verwendete Komponente mit einer Implementierung mit einer relationalen Datenbank
vorgestellt (siehe Kapitel 6). Ausgehend von den Problemen, die sich dabei ergeben haben, wird diese Implementierung mit der einer objektrelationalen Datenbank
verglichen (siehe Kapitel 7).
4
2
2.1
Requirements Engineering
Einleitung
Oft sind Fehler in der Softwareentwicklung auf eine schlechte Analyse zurückzuführen (vgl. u. a. [Rup 01]). Unklare, nicht oder nur oberflächlich formulierte Anforderungen können in einem Projektverlauf zu vielen Missverständnissen und späteren
Änderungen führen. Diese Änderungen sind unter Umständen sehr zeitaufwendig
oder gar nicht mehr möglich. Wie in [Rup 02, S. 1] beschrieben ist, stellen die Anforderungen das Fundament der Softwareentwicklung dar. Umso wichtiger ist es, dass
diese Phase der Softwareentwicklung mit besonderer Sorgfalt durchgeführt wird.
In diesem Kapitel werden die Grundlagen (Kapitel 2.2) und einige Techniken beschrieben, mit denen ein Requirements Document erstellt wird. Das Requirements
Document ist das Ziel der Entwicklungsphase Requirements Engineering und beschreibt die Anforderungen an ein zu erstellendes Softwaresystem.
Der Requirements Engineering Prozess besteht, wie in Abbildung 3 dargestellt,
aus drei Phasen.
Abbildung 3: Requirements Engineering Prozess [Som Saw 97, S. 113]
Zunächst werden die Anforderungen ermittelt (Requirements Elicitation). In Kapitel 2.4 wird gezeigt, wie durch Befragung der System Stakeholder, Analyse des IstZustands und Untersuchung der vorhandenen Unterlagen dabei vorgegangen wird.
System Stakeholder sind Personen, die das System direkt oder indirekt benutzen. Beispiele für System Stakeholder sind Kunden, Administratoren, Manager und
Mitarbeiter.
Nachdem die Anforderungen erhoben wurden, werden diese auf ”Schwächen” hin
untersucht. In Kapitel 2.5 wird beschrieben, wie inkonsistente, unvollständige, fehlerhafte und unvollständige Anforderungen erkannt werden. Die Fragen und Probleme,
5
die sich bei den ”fehlerhaften” Anforderungen ergeben, müssen weiter hinterfragt
werden (Requirements Negotiation), was zu neuen oder geänderten Anforderungen
führen kann. Wie in Abbildung 3 dargestellt, ist der Requirements Engineering Prozess ein zyklischer, d. h., die geänderten oder neu hinzugekommenen Anforderungen
müssen wiederum analysiert werden. Im Idealfall ist der Requirements Engineering
Prozess beendet, wenn alle Unstimmigkeiten beseitigt sind.
Parallel zu diesen drei Phasen müssen die Anforderungen aufgeschrieben werden.
Bei der Beschreibung der Anforderungen ergeben sich u. a. folgende Fragen, die im
Kapitel 2.3 beantwortet werden:
• Wie werden die Anforderungen in dem Requirements Document strukturiert?
• Wie werden die einzelnen Anforderungen beschrieben?
• Wie können Systemmodelle unterstützend eingesetzt werden?
2.2
Definitionen
Bevor auf die einzelnen Phasen des Requirements Engineering Prozesses eingegangen
wird, werden in diesem Abschnitt einige Begrifflichkeiten und Grundlagen beschrieben.
2.2.1
Was sind Requirements?
In [Som Saw 97, S. 5, eigene Übersetzung] wird die Frage folgendermaßen beantwortet:
”Requirements (=Anforderungen) sind die Spezifikation von dem, was implementiert werden soll. Sie beschreiben die Benutzermöglichkeiten, die generellen Systemrechte (Beispiel: Personalinformationen sind nur einsehbar, wenn sich der Benutzer
authentifiziert hat), die generellen Bedingungen an das System (Beispiel: alle 10
Sekunden soll ein Sensorwert ausgelesen werden) und die Bedingungen an den Entwickler (Beispiel: Das System soll in C++ entwickelt werden)”.
2.2.2
Definition: Requirement
Nach [IEEE610.12-1990] wird eine Requirement folgendermaßen definiert:
1. Eine Bedingung oder Fähigkeit von einem Benutzer, die benötigt wird, um ein
Problem zu lösen oder eine Zielsetzung auszuführen.
2. Eine Bedingung oder Fähigkeit, die beschlossen wird oder die ein System oder
eine Komponente besitzen muss, um einen Vertrag, Standard, Spezifikation
oder andere formell aufgelegte Dokumente zu erfüllen.
3. Eine dokumentierte Repräsentation der Bedingungen von (1) und (2).
6
2.2.3
Bedingungen an ein Requirement
Nach [IEEE830-1998] sollten Anforderungen mindestens folgende Bedingungen erfüllen:
korrekt: Anforderungen müssen die (wahren) Kundenanforderungen widerspiegeln.
unmissverständlich bzw. eindeutig : Anforderungen dürfen keinen Interpretationsspielraum zulassen.
vollständig: Vor allem die Bedingungen sind zu überprüfen, Ausnahme- und Sonderfälle sind zu prüfen.
konsistent: Jede Anforderung muss für sich allein konsistent sein.
sortiert nach Bedeutung und Stabilität: Durch die Vergabe von Prioritäten
können Anforderungen nach ihrer Wichtigkeit sortiert werden.
testbar: Anhand einer Anforderung sollte sich mühlos ein Testfall ableiten können.
änderbar: Änderungen an einer Anforderung dürfen keine Inkonsistenz zu anderen
Anforderungen entstehen lassen. Ggf. müssen Abhängigkeiten der Anforderungen untereinander definiert werden, um diese änderbar zu machen.
nachvollziehbar: Es sollte nachvollziehbar sein, warum die Anforderung so gestellt
wurde, z. B. durch Referenzen auf zusätzliche Unterlagen oder anderen Dokumenten.
2.2.4
Was ist Requirements Engineering?
Requirements Engineering beschreibt die Aktivitäten, die nötig sind um Anforderungen zu ermitteln, zu beschreiben und auf Korrektheit, Vollständigkeit, Konsistenz und Relevanz zu überprüfen. Der Begriff Engineering impliziert, dass es sich
um eine systematische und wiederholbare Technik handelt (vgl. [Som Saw 97, S. 5]).
Bei den Anforderungen unterscheidet man außerdem zwischen funktionalen und
nicht-funktionalen Anforderungen. Nicht-funktionale Anforderungen sind z. B. Qualitätsanforderungen oder Randbedingungen und lassen sich oft nur sehr schwer oder
gar nicht messen. Funktionale Requirements beschreiben die (messbaren bzw. testbaren) Eigenschaften des Systems. Dabei ist die Trennung nicht ganz eindeutig und
viele nicht-funktionale Anforderungen lassen sich durch detailliertere Beschreibung
in funktionale und damit auch messbare Anforderungen umwandeln (vgl. [Gli 04,
Kap. 5.4]). Wie in Kapitel 3.2.1 noch zu sehen sein wird, können nicht-funktionale
Anforderungen in funktionale umgewandelt werden.
7
2.3
2.3.1
Das Requirements Document
Einleitung
Das Requirements Document beschreibt die Anforderungen für die Kunden, die Benutzer und die Entwickler. Es sollte in einer einfachen, für jedermann verständlichen
Sprache geschrieben sein. Das Requirements Document soll die verschiedensten Interessen und Sichtweisen der Benutzer- und Personengruppen widerspiegeln (siehe
[Som Saw 97, S. 38 f.].
• Dem Kunden3 dient das Requirements Document zur Überprüfung, ob seine
Anforderungen richtig verstanden wurden.
• Dem Projektmanagement dient das Requirements Document als Grundlage
für die Angebotserstellung und die Planung des Entwicklungsprozesses.
• Dem Systementwickler dient das Requirements Document als Grundlage für
den Entwurf und die Implementierung des Systems.
• Die Tester sollen aus den Anforderungen Testfälle ableiten können, um zu
überprüfen, dass die Anforderungen auch erfüllt sind.
Sehr häufig werden in diesem Zusammenhang die Begriffe Pflichtenheft und Lastenheft verwendet. In einem Lastenheft werden die Anforderungen aus Sicht des
Kunden aufgeschrieben. Die erweiterte Version des Lastenheftes ist das Pflichtenheft. Im Pflichtenheft werden die Anforderungen des Kunden verfeinert und konkrete
Realisierungsansätze ermittelt. Kurz gesagt beschreibt das Lastenheft, was zu lösen
ist und warum. Das Pflichtenheft erweitert das Lastenheft um das Wie und Womit. Das Pflichtenheft wird dem Auftraggeber vorgelegt und dient als Grundlage
für einen Vertrag zwischen dem Systementwickler und Auftraggeber (vgl. [ViSEK]).
In der Realität gibt es dabei oft Probleme, da das Pflichtenheft nicht immer konform zum Lastenheft ist. Beim Requirements Engineering gibt es ein Requirements
Document, was das Pflichten- und das Lastenheft ersetzen soll.
2.3.2
Requirements beschreiben
Anforderungen müssen so beschrieben werden, dass sie kurz, verständlich und eindeutig sind. Sie dürfen keinen Interpretationsspielraum zulassen und müssen die in
Kapitel 2.2.3 genannten Bedingungen erfüllen.
3
Der Kunde wird im weiteren Verlauf als Auftraggeber bezeichnet und ist der beschriebene
Abteilungsleiter.
8
Die Beschreibung solcher Anforderungen ist nicht ganz einfach, da kurze einfache
Formulierungen und vollständig Beschreibungen mit allen Sonder- und Ausnahmefällen oft einen Widerspruch darstellen. Ein weiteres Problem stellen die sehr unterschiedlichen Lesergruppen (siehe Kapitel 2.3.1) dar. Die Anforderungen sollen so
gestellt werden, dass ein Entwickler daraus eindeutig ableiten kann, was entwickelt
werden soll, und das Projektmanagement beispielsweise muss die gleichen Anforderungen ebenfalls verstehen können, um daraus ein Angebot erstellen zu können. Dies
ist vor allem bei einer rein natürlichsprachlichen Anforderungsbeschreibung oft sehr
schwierig.
Ein weiteres Problem mit der natürlichsprachlichen Anforderungsbeschreibung
soll das folgende Beispiel verdeutlichen (vgl. auch [Som Saw 97, S. 141 ff.]): ”Wenn
der Benutzer eingeloggt ist und den Button Administration bestätigt hat, kann er,
wenn er das Benutzerrecht ’Administrator’ besitzt und sofern kein anderer...”
Weitere Probleme, die sich nach Sawyer und Sommerville (vgl. [Som Saw 97, S.
147]) bei einer natürlichsprachlichen Beschreibung ergeben, sind, dass diese Terminologien meist in einer inkonsequenten und unsauberen Form verwendet werden.
Die Verwendung einer Spezifikationssprache für Requirements hat den Nachteil,
dass sie wahrscheinlich nicht von jedem sofort verstanden wird und erst erlernt
werden muss (vgl. [IEEE830-1998, Kapitel 4.3.2.2]). Wie schon erwähnt wurde, sind
die Systementwickler nur eine der Lesergruppen.
2.3.3
Systemmodellierung
Systemmodelle beschreiben einen bestimmten Aspekt eines Systems. Sie ergänzen
das Requirements Dokument, um die Anforderung verständlicher zu beschreiben,
und sollten parallel zur Anforderungsermittlung erstellt werden (vgl. [Som Saw 97,
S 299]).
Systemmodelle helfen zum einen die Anforderungen besser zu verstehen und
können es erleichtern, mit dem Auftraggeber zu kommunizieren. Zwei wichtige Typen von Systemmodellen sind verhaltensorientierte und strukturelle Modelle (vgl.
[Som Saw 97, S. 307]). Die strukturellen Modelle beschreiben die Entitäten und die
Abhängigkeiten dieser zueinander sowie die Struktur des Systems oder der Komponenten. Ein Beispiel für die verhaltensorientierten Modelle sind Statechart Diagramme oder Timeline Diagramme.
Prinzipiell sollten die Systemmodelle die gleichen Anforderungen wie die eigentlichen Anforderungen erfüllen, da diese genauso von allen genannten Lesergruppen
verstanden werden sollen.
9
2.3.4
Struktur des Requirements Documents
Im Requirements Document sollen die gesammelten und analysierten Informationen
(Requirements, Systemmodelle, Beschreibung der Stakeholder) in einer strukturierten Form dargestellt werden.
Zu diesem Zweck wurde ein Standard entwickelt, der in [IEEE830-1998] beschrieben ist und als Grundlage für das Requirements Document dienen kann. Dieser
Standard ist sehr allgemein gehalten, gibt aber trotz allem eine Reihe von Punkten
vor, die grundsätzlich in jedem Requirements Documents enthalten sein sollten. Der
Stuktur des Hauptteils ist dabei offen gehalten. Es werden lediglich Templates für
mögliche Strukturen vorgeschlagen. Die Verwendung eines Standards hat den Vorteil, dass nicht jede Firma das ”Rad neu erfinden” muss und auf die Erfahrungen
anderer zurückgegriffen werden kann. Neue Mitarbeiter, die ein Requirements Document lesen, was einem firmeneigenen Standard folgt, müssen sich erst einarbeiten,
um mit diesem arbeiten zu können. Softwareunterstützte Tools, die auf diesem Standard basieren, sind in der Regel preiswerter als selbst entwickelte Tools, welche auf
dem firmeneigenen Standard aufbauen.
2.4
2.4.1
Anforderungen erheben (Elicitation)
Einleitung
In diesem Abschnitt geht es darum, die Anforderungen zu ermitteln. Haupt- und
Mittelpunkt bei der Anforderungserhebung sind die Stakeholder (vgl. [Rup 02, S. 140
f.]). Durch eine erste Befragung des Auftraggebers (siehe 2.4.2) werden die generellen
Ziele und die ersten Stakeholder ermittelt. In Abschnitt 2.4.3 werden Techniken
vorgestellt, mit denen diese befragt werden können. Parallel zu den Befragungen
der Stakeholder können weitere Techniken verwendet werden, die in Abschnitt 2.4.4
vorgestellt werden.
2.4.2
Erste Schritte
Als ersten Schritt in der Anforderungserhebung wird in [Som Saw 97, S. 66 ff.] eine
Machbarkeitsstudie vorgeschlagen. Eine Machbarkeitsstudie im eigentlichen Sinne
war diesem Fall aus zeitlichen Gründen nicht möglich. Basierend auf dem Fragenkatalog von [Som Saw 97, S. 66 ff.] können die in Abbildung 4 dargestellten Fragen
zum ersten Interview des Auftraggebers dienen. Durch die letzte Frage werden die
ersten Stakeholder ermittelt.
2.4.3
System Stakeholder identifizieren und befragen
Ein sehr wichtiger Punkt in der Anforderungsermittlung ist die Ermittlung und Befragung der Stakeholder. Wenn nicht alle Stakeholder ermittelt werden, besteht die
Gefahr, dass wichtige Anforderungen vergessen werden (vgl. [Som Saw 97, S. 72 ff.]),
10
1. Was ist das Ziel des Systems?
2. Was wäre die Konsequenz, wenn wir das System nicht entwickeln?
3. In welchen direkten und indirekten Wegen beeinflusst das System die Geschäftsprozesse?
4. Welche kritischen Prozesse muss das System berücksichtigen?
5. Welche kritischen Prozesse werden von dem System nicht unterstützt?
6. Wie beeinflusst das System die vorhandenen Systeme?
7. Was sind die Bedingungen an den Entwickler?
8. Welche Geschäftsbereiche sind in das System integriert und müssen betrachtet
werden?
Abbildung 4: Erste Befragung des Auftraggebers
oder wie in [Rup 02, S. 148] beschrieben ist: ”Vergessene Stakeholder sind vergessene Anforderungen”. Ein nachträgliches Hinzufügen von Anforderungen ist dann nur
noch mit sehr viel Aufwand möglich.
Durch die Geschäftsbereiche, die in das System integriert werden sollen, lassen
sich die ersten Benutzergruppen ermitteln (vgl. letzte Frage aus Abbildung 4). Im
Folgenden werden einige Befragungstechniken vorgestellt, mit denen die Anforderungen von der Stakeholder ermittelt werden können. Ein grundsätzlicher Vorteil
bei der Befragung der Stakeholder ist, dass sich diese durch die Befragung stärker
an der Entwicklung beteiligt fühlen, was die Akzeptanz an das neue System erhöht.
Fragebögen
Fragebögen sind vor allem dann eine geeignete Technik, wenn in kurzer Zeit viele
Informationen gesammelt werden sollen. Sie haben allerdings den Nachteil, dass die
befragten Personen keine Fragen stellen können, und setzen voraus, dass bekannt
ist, welche Informationen benötigt werden, was in dieser Arbeit oft nicht der Fall
war.
Einzelinterview
In [Sah 00, S. 21] werden zwei Arten des Einzelinterviews beschrieben.
Bei einem geschlossenen Interview werden zuvor Fragen vorbereitet, die dem
entsprechenden Stakeholder gestellt werden. Rück- und Verständnisfragen sind zwar
11
möglich, aber diese Technik verlangt ein strenges Vorgehen nach den vorher definierten Fragen und erlaubt nicht, dass auf die Fragen weiter eingegangen werden kann.
Wie in [Sah 00, S. 21] dargestellt ist, besteht bei dieser Technik das Problem, dass
wichtige Aspekte nicht berücksichtigt werden, die durch ein ”freies Reden” aufkommen könnten. Einer der Vorteile dieser Methode ist, dass kein aufwendiges Protokollieren nötig ist und die gleiche Befragung bei einem anderen Repräsentanten der
Stakeholdergruppe durchgeführt werden kann.
Die zweite Möglichkeit ist das offene Interview. In diesem Fall wir eine zentrale Frage bzw. ein zentrales Ziel der Befragung definiert und der Befragende kann
abhängig von den gegebenen Antworten weitere Fragen stellen. Bei dieser Technik
besteht das Problem, dass auf unwichtige Themen abgeschweift werden kann und
sowohl die Fragen als auch die Antworten müssen protokolliert werden. Außerdem
ist ein geschlossenes Interview in gleicher Form nicht reproduzierbar.
Gruppeninterview
In einem Gruppeninterview wird eine repräsentative Menge an Stakeholdern ermittelt, mit denen gemeinsam die Anforderungen oder Probleme analysiert werden. Die
Vorgehensweise ist dabei ähnlich der des offenen Interviews. Das Gruppeninterview
hat zusätzlich den Vorteil, dass sich die Stakeholder gegenseitig Feedback geben
können und durch die gemeinsame Analyse schneller eine Lösung erreicht werden
kann. Eine Diskussion in einer Gruppe hat aber auch einige weitere Nachteile im
Vergleich zum offenen Einzelinterview, wie z. B. die Einschüchterung von Befragten
durch Anwesenheit eines Vorgesetzten oder Kollegen.
Brainstorming
Eine spezielle Form der Gruppenbefragung ist das Brainstorming. Brainstorming
besteht in zwei Phasen:
In der ersten Phase werden alle Ideen gesammelt und aufgeschrieben, ohne dass sie
bewertet werden. Dabei können auch ungewöhnliche Ideen aufkommen oder sich beliebige Kombinationen ergeben. Erst in der zweiten Phase werden die Ideen bewertet
und die unsinnigen Ideen verworfen oder korrigiert.
2.4.4
Unterstützende Analysetechniken
Im Folgenden werden einige Techniken beschrieben, die sich nicht auf die Befragung
der Stakeholder beziehen und unterstützend eingesetzt werden können. Diese Techniken allein sind oft wenig hilfreich, aber eine wertvolle Ergänzung zu den Befragungen.
Analyse von Dokumenten und Vorgängersystemen
Vor allem existierende Dokumente aller Art zu diesem Thema können eine hilfreiche
Ergänzung darstellen. Gescheiterte Entwicklungen oder existierende Vorgängersysteme können bereits einige Probleme gelöst haben und sind ebenfalls eine hilfreiche
12
Unterstützung.
Prototyping
Eine weitere Technik ist das Prototyping. Beim Prototyping werden bereits einige
Funktionalitäten in einer sehr frühen Phase implementiert, um das Benutzerverhalten zu demonstrieren. Bei dieser Technik gibt es zwei Vorgehensweisen: das explorative und das evolutionäre Prototyping.
Beim explorativen Prototyping werden die Benutzermöglichkeiten des zu erstellenden Systems an einer einfachen Anwendung dargestellt, ohne dass konkrete Funktionalitäten existieren. Dieser Prototyp hat den Zweck, die Beschreibung der Anforderungen zu unterstützen, und wird nach dem Requirements Engineering nicht
weiter verwendet. Ein explorativer Prototyp sollte mit einfachsten Mitteln erstellt
werden können (z. B. Drag-and-Drop4 ). Obwohl ein explorativer Prototyp zusätzliche Zeit kostet, kann sich diese investierte Zeit doch lohnen, da eine ”funktionsfähige”
Benutzeroberfläche oft mehr aussagt als eventuell umständliche Beschreibungen.
Im Gegensatz dazu gibt es das evolutionäre Prototyping. Dieser Prototyp wird
weiter verwendet und entwickelt, um dann schließlich daraus ein fertiges System zu
erhalten. Durch die Verwendung eines evolutionären Prototypen hat der Auftraggeber die Möglichkeit, den Entwicklungsprozess mit zu verfolgen. Fehler und Probleme
können so frühzeitig erkannt werden und die Stakeholder fühlen sich stärker an der
Entwicklung beteiligt. Allerdings können dadurch auch immer weitere Anforderungen entstehen, die erst beim Prototyp erkannt werden. Da der evolutionäre Prototyp
gleichzeitig ein Teil des endgültigen Systems darstellt, kann es aber sehr schwierig
werden, diese Änderungen mit zu berücksichtigen.
Viewpoint-orientierter Ansatz
Ein weiterer Ansatz ist der Viewpoint-orientierte Ansatz. Die verschiedenen Sichten
der Stakeholder und die verschiedenen Aspekte der Software können separat betrachtet werden. Durch die Betrachtung der Anforderungen unter einem bestimmten
Gesichtspunkt (View) kann die Komplexität der Anforderungen vermindert werden
und ist somit leichter verständlich. Viewpoints können neben der Anforderungserhebung auch zum Analysieren und in der Beschreibung der Anforderungen verwendet
werden. Wie schon in 2.3.2 erwähnt wurde, stellt es eine Schwierigkeit dar, Anforderungen so zu formulieren, dass sie von allen Lesergruppen verstanden werden. Zwei
mögliche Viewpoints, die betrachtet werden könnten, sind die Benutzeranforderungen, und zwar einmal mit und einmal ohne Systemanforderungen (vgl. [Som Saw 97,
S. 7]). Weitere Möglichkeiten für die Ermittlung von Viewpoints sind die referenzierten Quellen oder die Benutzerrechte.
4
”ziehen und loslassen”, d. h., die Benutzeroberfläche wird zusammengeklickt
13
2.5
Anforderungen analysieren und neu verhandeln
Im Folgenden werden zwei Ansätze vorgestellt, mit denen Anforderungen auf Schwächen hin untersucht werden können. Schwächen in Anforderungen sind nichts Schlechtes. In [Som Saw 97, S. 125] werden sie als natürlich und unvermeidbar dargestellt.
Der erste Ansatz ist die Analyse auf sprachlicher Ebene. Anhand der Formulierungen sollen Schwächen erkannt werden. Der zweite Ansatz basiert auf der inhaltlichen Analyse. Dabei wird überprüft, ob die Anforderungen die in Kapitel 2.2.3
genannten Bedingungen erfüllen und konform zueinander sind.
Die gefundenen Schwächen in den Anforderungen müssen anschließend dem entsprechenden Stakeholder oder dem Auftraggeber vorgetragen werden. Durch Beschreibung des entstandenen Problems oder Konflikts muss gemeinsam eine Lösung
gefunden werden (vgl. [Som Saw 97, S. 125 ff.]. Wie bereits erwähnt wurde, können an dieser Stelle neue Anforderungen entstehen, sich Anforderungen ändern oder
neue Stakeholdergruppen herauskristallisieren.
2.5.1
Anforderungen sprachlich überarbeiten
Die sprachliche Analyse von Anforderungen basiert auf der Idee, die Formulierungen der Anforderungen zu untersuchen und anhand dieser Schwächen und Fehler
zu ermitteln. In [Rup 01] werden drei Arten der sprachlichen Analyse vorgestellt:
Tilgung, Generalisierung und Verzerrrung.
Bei der sprachlichen Tilgung werden Informationen weggelassen. Oft ist es sinnvoll, zu viele Details in der ersten Phase der Anforderungsermittlung zu vermeiden,
um das Problem als Ganzes zu verstehen. Wurden die Anforderungen aber bereits
erhoben und sollen analysiert werden, müssen diese Tilgungen wieder hinterfragt
werden um die Anforderungen korrekt darzustellen. Eine Form der Informationstilgung sind unvollständig definierte Prozesswörter5 . Diese müssen ermittelt werden
und weiter hinterfragt werden. Eine weitere Form der Informationstilgung sind unvollständige Komparative oder Superlative. Diese benötigen immer einen Bezugspunkt, der, wenn er spezifiziert ist, auch messbar sein sollte.
Durch Generalisierung bzw. Verallgemeinerungen werden Anforderungen oft
zu ungenau beschrieben. Sonder- und Ausnahmefälle werden nicht berücksichtigt,
wodurch die Anforderungen unvollständig werden. Zur Überprüfung einer Generalisierung können Universalquantoren gesucht werden (siehe [ViSEK]), wie zum
Beispiel ”alle”, ”jeder”, ”nie”, ”immer”. Diese Begriffe sind ein Anzeichen für eine
Generalisierung und es muss hinterfragt werden, ob diese Anforderung wirklich für
alle bzw. für keinen der möglichen Fälle eintritt. Unvollständig spezifizierte Bedin5
Prozesswörter sind Wörter, die einen Prozess beschreiben.
14
gungen können ebenfalls Anzeichen für Schwächen in den Anforderungen darstellen.
Dabei ist zu hinterfragen, was passiert, wenn die gegebene Bedingung nicht eintritt.
Substantive ohne Bezugspunkt müssen ebenfalls hinterfragt werden, ob diese nicht
eine bestimmte Person oder einen Gegenstand darstellen. Beispiele für solche Substantive sind: ”die Daten”, ”die Funktion” oder ”das System” (vgl. [ViSEK]).
Durch Verzerrung werden zeitlich zusammenhänge Informationen zusammengefasst. Ein Beispiel für eine Verzerrung ist Nominalisierung. Dabei wird ein Prozess
zu einem Ereignis umformuliert. Beispiele sind ”das Drucken” oder ”das Melden”.
Hinter diesen Anforderungen könnte sich ein Prozess verbergen. Ein weiteres Anzeichen für Schwächen in den Anforderungen sind Wörter wie ”machen”, ”können”
oder ”haben”. Diese drücken Anforderungen oft nur unvollständig aus (siehe auch
[Rup 02, S. 208 ff.]).
2.5.2
Checklisten zur Überprüfung
Die Verwendung von Checklisten zur Überprüfung der Anforderungen hat den Vorteil, dass die Anforderungen systematisch und wiederholbar untersucht werden können. Jede Anforderung wird so lang gegen jeden Checklisteneintrag getestet, bis
alle ”Fehler” beseitigt sind. In [Som Saw 97, S. 117-120] wird eine initiale Checkliste
vorgegeben:
voreiliger Entwurf: Beschreibt die Anforderung bereits Entwurfs- oder Implementierungsdetails?
Kombinierte Anforderung: Beschreibt diese Anforderung wirklich eine einzelne
Anforderung, oder könnte sie in mehrere unterteilt werden?
Unwichtige Anforderung: Ist diese Anforderung wirklich nötig, oder beschreibt
sie nur eine kosmetische Verschönerung?
Konsistent zu den Unternehmenszielen: Ist diese Anforderung konform zu dem
Unternehmenszielen?
Anforderungsmehrdeutigkeit: Kann diese Anforderung von verschiedenen Personen unterschiedlich interpretiert werden? Was sind die möglichen Deutungen
dieser Anforderung?
Anforderungsrealismus: Ist die Anforderung mit den gegebenen Mitteln und
Werkzeugen realisierbar?
Testbarkeit: Ist die Erfüllung dieser Anforderung testbar? Kann ein Tester anhand
dieser Anforderung einen Testfall ableiten, der zeigt, dass das System diese
Anforderung erfüllt?
15
Wenn die oben dargestellten Checklistenpunkte mit den Bedingungen an die
Requirements aus Kapitel 2.2.3 verglichen werden, sieht man, dass diese Checkliste
prinzipiell überprüft, ob die genannten Bedingungen an die Requirements erfüllt
sind. Die in Kapitel 2.5.1 dargestellte sprachliche Analyse kann ebenfalls in Form
einer Checkliste verwendet werden.
16
3
Analyse mit Requirements Engineering
3.1
3.1.1
Anforderungen erheben
Erste Schritte
Durch eine erste Befragung des Auftraggebers6 , wie in Kapitel 2.4.2 beschrieben,
wurden die ersten Anforderungen ermittelt. Dabei ergaben sich u. a. die folgenden
Informationen. Die detailliertere und überarbeitete Beschreibung befindet sich in
[ReqDoc, Kapitel 1.1 und 2].
Ziele des Systems:
• Es soll ein webbasiertes Zeiterfassungssystem erstellt werden, wo die Mitarbeiter ihre geleistete Arbeitszeit den Projekten zuschreiben können. Die
geleistete Arbeitszeit wird in prozentualer Form auf die vorhandenen Projekte verteilt.
• Die Projekte wiederum bestehen aus einer Menge von Fachgruppen. Die
Mitarbeiter sollen ihre den Projekten zugewiesene Arbeitszeit auf diese
Fachgruppen verteilen.
• Außerdem existieren Aufgabenkataloge, die unabhängig von Projekten
und Fachgruppen sind. Jede zugewiesene Arbeitszeit in den Fachgruppen
muss von den Mitarbeitern auf die Aufgabenkataloge verteilt werden.
• Bei ”kleineren” Projekten existieren keine Fachgruppen. Die in diesen Projekten zugewiesene Arbeitszeit wird dann direkt auf die Aufgabenkataloge
verteilt.
• Es sollen zahlreiche Berichte (Reports) erzeugt werden können, die verschiedenste Daten in aufbereiteter Form darstellen.
• Gleiche Berichte mit gleichen Parametern sollen jederzeit die gleichen
Daten anzeigen, d. h., ein nachträgliches Ändern von Daten darf keine
Änderung in den Berichten verursachen. Folgendes Beispiel soll diese Anforderung erklären:
Wird eine Kostenstelle eines Mitarbeiters geändert, so würde ein Bericht
mit allen Stunden pro Kostenstelle nach der Änderung eine andere Ausgabe erzeugen.
Konsequenz ohne das System:
• Ohne dieses System wäre ein Aufbau von Kennzahlen für die Personalentwicklung nicht möglich (siehe auch [ReqDoc, S. 1]), d. h., die oben
genannten Berichte müssten mühselig von Hand erstellt werden.
6
dem Abteilungsleiter der Abteilung Hardware- und Softwareentwicklung
17
Kritische Prozesse:
• Das System darf personengebundene Leistungskontrolle nicht ermöglichen, da der Betriebsrat dieses System sonst nicht zulassen würde.
Grenzen des Systems:
• Eine Anbindung an das existierende SAP-System ist aus politischen und
datenschutztechnischen Gründen nicht möglich.
Bedingungen an den Entwickler:
• Die Zeiterfassung soll eine webbasierte Applikation sein, d. h., die Kommunikation erfolgt über einen Webbrowser.
• Für die Zeiterfassung soll ASP.NET und die Programmiersprache C#
verwendet werden.
Geschäftsprozesse oder andere Systeme beeinflusst die Zeiterfassung nicht (siehe
Frage 3 und 6 aus Kapitel 2.4.2). Wie an diesen Antworten zu sehen ist, stellten sich
dabei weitere Fragen, die nicht auf Anhieb beantwortet werden konnten:
• Woher kommen die Projekte, wenn es keinen Zugriff auf die Projektdaten des
SAP-Systems gibt?
• Wenn die Mitarbeiter nur prozentual ihre Arbeitszeit den Projekten zuordnen, woher kommen dann die absoluten Arbeitszeiten, um daraus Reports zu
erstellen?
Aus dieser Befragung ergaben sich die in Abbildung 5 dargestellten Geschäftsbereiche bzw. Stakeholder (vgl. mit Frage 8 und 6 in Abbildung 4 auf Seite 11).
Abbildung 5: Kommunikation zwischen den Stakeholdern
18
3.1.2
Analyse des Ist-Zustandes
Basierend auf dem Ist-Zustand wurden die ersten Stakeholder ermittelt. Das Hauptziel der Anwendung ist es, Berichte mit Arbeitsstunden über Projekte, Fachgruppen
und Aufgabenkataloge zu erhalten. Im Vorgängersystem wurden die Berichte, wie
in Abbildung 6 dargestellt, erstellt.
Abbildung 6: Activity Diagram des Ist-Zustandes für die Berichtserstellung
Die Arbeitszeiten der Mitarbeiter werden über ein externes System erfasst, was
nicht ersetzt werden kann. Diese Zeiten stehen dann in einem SAP-System dem Controller zur Verfügung. Über ein Excell-basiertes System müssen die Mitarbeiter ihre
Arbeitszeiten nach Ablauf einer jeden Woche auf vorhandene aktive Projekte verteilen. Der Controller wandelt diese relativen Arbeitszeiten in den Projekten zusammen
mit den absoluten Arbeitszeiten aus dem SAP-System in absolute Arbeitszeiten in
den Projekten um. Über die Zuordnung der Mitarbeiter zu bestimmten Kostenstellen kann er daraus einen Stundenreport für Projekte nach Kostenstellen und nach
Mitarbeitern erstellen und diese dem Abteilungsleiter zur Verfügung stellen.
Die Projektverwaltung erfolgt wie in Abbildung 7 dargestellt. Die Projekte werden vom Projektmanager7 in einer Exceltabelle verwaltet. Wenn ein neues Projekt
beschlossen8 wird, wird der Projektmanager benachrichtigt. Das neue Projekt wird
dann in der Exceltabelle angelegt. Die Projektnummer wird dabei manuell ermittelt.
Anschließend wird ein Schreiben aufgesetzt, indem u. a. der Controller benachrichtigt wird, dieses Projekt im SAP-System anzulegen. Das Beenden eines Projekts
7
Projektmanager ist in diesem Fall die Sekretärin des Bereichsleiters, der wiederum der Vorgesetzte des Abteilungsleiters ist.
8
in einem Projektteammeeting, was für diese Anwendung aber irrelevant ist
19
Abbildung 7: Zustände eines Projekts
erfolgt in einer ähnlichen Form.
Wie an dieser Beschreibung zu sehen ist, ergeben sich bei dieser Vorgehensweise
viele Probleme. Einige Beispiele hierfür sind die folgenden:
• Die Projekte existieren redundant in drei verschiedenen Systemen: in der Exceltabelle des Projektmanagers, im SAP-System, und der Auftraggeber besitzt
ebenfalls ein eigenes System.
• In dem Excel-basierten System des Controllers kann ein Projekt nur hinzugefügt werden. Abgeschlossene Projekte zu löschen oder wenigstens aus der Liste
der Projekte zu entfernen ist nicht möglich.
• Der Controller muss bis zu einem festgesetzten Datum jeden Monats einen
Bericht mit Arbeitsstunden über Kostenstellen und Projekte erstellen. Wurden Arbeitszeiten von Mitarbeitern nicht zugewiesen, weil sie beispielsweise
am Ende der Woche in den Urlaub gegangen sind, ohne ihre Zeitverteilung
vorzunehmen, so muss der Controller die Zeitverteilung für diese Mitarbeiter
vornehmen, da alle Arbeitsstunden auf Projekte verteilt werden müssen.
3.1.3
Befragung der Stakeholder mit verschiedenen Techniken
Für die Befragung der Stakeholder wurden jeweils die in Kapitel 2.4.3 dargestellten
unterschiedlichen Techniken angewendet.
Gruppeninterview
Die Befragung der Mitarbeiter erfolgte in Form eines (geschlossenen) Gruppeninterviews (vgl. Kapitel 2.4.3). Vier repräsentative Mitarbeiter und der Auftragge20
ber sollten klären, wie die Zeitverteilung vorgenommen wird. Dabei sollten folgende
Punkte geklärt werden:
• Da Unstimmigkeiten über die Verwendung von prozentualer oder absoluter
Zuordnung existierten, sollten die Stakeholder diese Frage beantworten.
• Sollen Fachgruppen global verwaltet und den Projekten zugeordnet werden
oder werden sie für jedes Projekt neu angelegt?
• Der Nutzen für die Mitarbeiter sollte geklärt werden, d. h. ob es für sie sinnvoll
wäre, wenn sie Berichte über ihre zugeordneten Zeiten erhalten würden.
Der letzte Punkt wurde im Wesentlichen nur deswegen gewählt, um die Akzeptanz der Mitarbeiter zu steigern und ihnen einen Vorteil darzubieten, der das neue
System für sie besitzt. Ein interessantes Phänomen war, dass sich die Meinungen
ziemlich schnell zu einer gemeinsamen Gruppenmeinung entwickelten. Interessant
war außerdem, dass die Mitarbeiter Prozente eingeben wollten, obwohl sie ihre Arbeitszeiten als Stunden sehen wollten, so wie zuvor vom Auftraggeber schon gefordert
wurde. Nach den Angaben der Stakeholder besteht eine Fachgruppe im Wesentlichen aus einem festen Kern von Mitarbeitern. Um aber den Administrationsaufwand
für die Verwaltung der Fachgruppe zu vermeiden, sollen diese für jedes Projekt neu
angelegt werden.
Brainstorming
Die möglichen Berichte, die durch die Zeiterfassung erstellt werden können, wurden in einem Brainstorming-Interview durchgeführt. Der entscheidende Vorteil des
Brainstormings liegt darin, dass ziemlich schnell viele Ideen entstehen. Allerdings
hat diese Technik den Nachteil, dass das gegebene Vorgehen auch streng eingehalten werden muss, was in diesem Fall nur halbwegs funktioniert hat. Ein weiterer
nachteiliger Punkt ist, dass es schwierig ist, die Ideen zu bewerten. Grundsätzlich
waren viele gute Ideen dabei, die aber in der gegebenen Zeit nicht realisierbar waren.
Einzelinterview
Die Befragung der Stakeholder Projektmanagement und Controller wurde als
Einzelinterview vorgenommen. Ein strenges Vorgehen in Form eines geschlossenen
Interviews (vgl. Kapitel 2.4.3) wurde nicht vorgenommen, um die Möglichkeiten
nicht von vornherein einzuschränken. Ein Problem stellte auch die Tatsache dar,
dass die Fragen nicht genau genug gestellt werden konnten, da nicht genau klar war,
was entwickelt werden sollte. Vor der Befragung wurde eine Liste mit Fragen vorbereitet, die als Richtlinie für das Interview diente.
Diese Technik hat sich als sehr vorteilhaft herausgestellt, da durch die vorgegebenen Fragen die Ziele des Interviews definiert waren und die Möglichkeiten trotzdem
21
nicht eingeschränkt wurden. Ein weiterer Vorteil war der, dass keine ”geschickte”
Moderatorfunktion des Befragenden nötig war und keine ”störenden” gruppendynamischen Prozesse berücksichtigt werden mussten.
Weitere Befragungen
Für die Befragungen nach entstandenen Widersprüchen und Schwächen der Anforderungen wurden direkte Befragungen der entsprechenden Stakeholder durchgeführt.
3.1.4
Beschreibung der Stakeholder
Im Folgenden werden die einzelnen Stakeholder beschrieben, die in Kapitel 3.1.2
ermittelt und in Kapitel 3.1.3 befragt wurden.
Mitarbeiter:
Bisher wurden nur Mitarbeiter erwähnt. Diese werden weiter unterteilt in interne
und externe Mitarbeiter.
Die internen Mitarbeiter arbeiten an den Projekten. An Ende jeder Woche müssen sie ihre Arbeitszeiten in prozentueller Form den vorhandenen Projekten, Fachgruppen und Aufgabenkatalogen zuordnen. Die absoluten Arbeitszeiten der internen
Mitarbeiter kommen von einem externen System, auf das aus datenschutztechnischen Gründen nicht zugegriffen werden kann. Die einzige Möglichkeit, diese Daten
zu erhalten, besteht darin, diese aus den Exceltabellen des Controllers zu extrahieren. Da diese Lösung aber sehr instabil ist, muss auf jeden Fall auch eine manuelle
Stundeneingabe existieren.
Die externen Mitarbeiter arbeiten, genau wie der interne Mitarbeiter, in Fachgruppen organisiert, an verschiedenen Projekten. Im Gegensatz zu den internen Mitarbeitern erscheinen externe Mitarbeiter nicht in den Berichten des Vorgängersystems. Die externen Mitarbeiter schreiben in unregelmäßigen Zeitabständen Rechnungen mit ihren geleisteten Arbeitszeiten und reichen diese beim Abteilungsleiter
ein.
In Kapitel 6.7.2 werden die internen und externen Mitarbeiter auch als Vertragsmitarbeiter bezeichnet, da es möglich sein soll, dass Mitarbeiter, die ihre Arbeitszeiten nicht den Projekten, Fachgruppen und Aufgabenkatalogen zuordnen müssen,
ebenfalls Fachsprecher oder Projektleiter sein können. Vertragsmitarbeiter sind sozusagen eine erweiterte Form der Mitarbeiter. Auf dieses Thema wird in den Kapiteln
6.7.2 und 6.8.2 noch eingegangen.
22
Projektmanager:
Der Projektmanager verwaltet die Projekte. Er legt die Projekte mit den entsprechenden Projektleitern an und kann diese beenden. Außerdem kann er den Projekten
Fachgruppen hinzufügen oder entfernen.
Controller:
Der Controller überwacht die Kosten der Projekte. Am Ende eines jeden Monats
benötigt er eine Projekt-Kostenstelle-Tabelle mit den geleisteten Arbeitsstunden,
die er so effizient wie möglich in das SAP-System eingeben möchte und dem Abteilungsleiter zur Verfügung stellt. Der Controller ist die einzige Schnittstelle, um die
absoluten Arbeitszeiten der internen Mitarbeiter zu erhalten.
Abteilungsleiter:
Der Abteilungsleiter verwaltet die Projekte und die darin enthaltenden Fachgruppen und Mitarbeiter seiner Abteilung. Sein Hauptinteresse an der Zeiterfassung
ist die Ausgabe der Berichte.
Administrator:
Diese Rolle existierte vorher nicht und ist nötig um verschiedene Daten, wie beispielsweise Kostenstellen, zu verwalten. Wie bereits erwähnt wurde, existiert keine
Möglichkeit, auf die Daten des SAP-Systems zuzugreifen. Die benötigten Informationen müssen redundant zu dem SAP-System verwaltet werden.
3.1.5
Unterstützende Analysetechniken
Zwei unterstützende Techniken bei der Anforderungserhebung sind die Analyse von
vorhandenen Dokumenten und die Analyse eines Vorgängersystems. Der Viewpointorientierte Ansatz ist vor allem dann vorteilhaft, wenn das Requirements Engineering
durch einen CASE-Tool9 unterstützt wird. Da in diesem Fall aber kein CASE-Tool
verwendet wurde, wurde auf diesen Ansatz verzichtet. Wie bereits beschrieben wurde, kann der Viewpoint-orientierte Ansatz auch für das Beschreiben von Anforderungen verwendet werden, was in diesem Fall getan wurde (siehe Kapitel 3.3.3).
Dokumente und Vorgängersystem:
Eine Access Datenbank, die für diese Zwecke entworfen worden war und verwendet wird, lieferte weitere Informationen, die durch die Befragungen nicht aufgekom9
Ein CASE (Code Aided Software Engineering)-Tools ist eine Software, welche den Softwareentwicklungsprozess unterstützt (siehe auch [Som 00] Kapitel 3).
23
men sind. Ein Beispiel dafür ist die weitere Unterteilung der internen Mitarbeiter
in Studenten, Aushilfen und ”normale” interne Mitarbeiter. Die vorhandene Exceltabelle des Stakeholders Projektmanager zeigte außerdem, dass Projekte weiter in
Projektgruppen organisiert sind.
Prototyping:
Zunächst wurde ein explorativer Prototyp (vgl. Kapitel 2.4.4) verwendet, der die
Funktionalität darstellen sollte. Dies waren einfache PHP-Scripte, die mithilfe einer
”Template-Klasse”10 HTML-Templates zu vollständigen HTML-Seiten zusammensetzen.
Der entscheidende Vorteil an dieser Technik ist die Trennung von Funktionalität
und Layout über einen sehr einfachen Mechanismus. Änderungen in den HTMLTemplates haben (fast) keine Auswirkungen auf Funktionalität (in diesem Fall nur
die Benutzersteuerung) und umgekehrt, wodurch sich ziemlich schnell und einfach
Oberflächen gestalten lassen.
Die Anforderung, dass die Zeiterfassung in ASP.NET und C# entwickelt werden
soll, kam erst etwas später dazu, wodurch sich ein Problem darstellte. ASP .NET
bietet einige grundlegend neue Techniken, wie in Kapitel 4 noch beschrieben wird.
Da mir diese Technik nicht vertraut war und nicht vorhergesehen werden konnte, was
mit ASP .NET möglich ist und was nicht, wurde die Art des Prototyping in einen
evolutionären geändert. Wie in Kapitel 2.4.4 beschrieben wurde, stellte sich dabei
ein Problem ein. Der Auftraggeber hatte die Möglichkeit, den Entwicklungsprozess
zu verfolgen und Änderungen an der definierten Benutzerführung wurden verlangt.
3.2
Analyse der Anforderungen
Gemäß Kapitel 2.5 werden im Folgenden einige Beispiel für ”Schwächen” in den
Anforderungen darstellt und die Konsequenzen daraus beschrieben. Vor allem der
natürlichsprachliche Ansatz (siehe 2.5.1) stellte sich als sehr effizient heraus, da
durch eindeutige Regeln Schwächen in den Anforderungen gefunden werden können.
Allerdings bot dieser Ansatz keine Möglichkeit, Inkonsistenzen der Anforderungen
untereinander zu analysieren. Der Checklisten-Ansatz aus Kapitel 2.5.2 war etwas
schwieriger durchzuführen, da diese Fragen ein großes Maß an Interpretationsfreiraum zuließen, d. h., der gleiche Test von einer anderen Person hätte u. U. zu einem
anderen Ergebnis geführt. Im Folgenden werden einige Beispiele dargestellt, die zeigen, welche Schwächen durch die Analyse der Anforderungen gefunden wurden.
10
Mehr Informationen zu der Klasse Template befinden sich unter http://phplib.sourceforge.net/
24
3.2.1
Anforderungen sprachlich überarbeiten
Tilgung:
Das folgende Beispiel zeigt eine Tilgung in Form eines unvollständig spezifizierten Prozesswortes, welche weiter hinterfragt werden musste:
Wurde beim Anlegen eines Projekts keine Projektnummer angegeben, so wird automatisch eine Projektnummer ermittelt, die dem Benutzer voreingestellt in der
Eingabemaske angezeigt wird.
Das Prozesswort ermittelt stellt dabei ein Schwäche dar. Die Frage ist hierbei,
wie wird diese Projektnummer ermittelt. Beim Hinterfragen des Stakeholders Projektmanager ergab sich, dass die Projektnummer abhängig von dem Projekttyp in
einem Projektnummerraum liegt.
Eine Konsequenz daraus ist, dass der Projekttyp um mindestens ein weiteres
Attribut erweitert wird. Außerdem musste geklärt werden, ob sich Projektnummern
immer in dem Projektnummerraum befinden müssen oder diese nur eine Empfehlung darstellen, wenn keine Projektnummer eingegeben wurde.
Ein weiteres Beispiel für eine Tilgung ist ein unvollständiger Komparativ. Wie
bereits in Kapitel 3.1.5 angesprochen wurde, existierten Unstimmigkeiten über das
Aussehen und den Ablauf der Benutzeroberfläche, da folgende Anforderungen nicht
genau genug betrachtet wurden:
Die Zeiterfassung soll eine einfach bedienbare und übersichtliche Benutzeroberfläche besitzen.
Die Frage, die sich hierbei u. a. stellt, lautet, wozu die Benutzeroberfläche einfach
bedienbar sein soll.
Dies ist auch gleichzeitig ein Beispiel für eine nicht-funktionale Anforderung (vgl.
Kapitel 2.2.4), die durch genauere Beschreibung zu einen funktionalen umgeformt
werden musste.
Generalisierung:
Ein Beispiel für eine Generalisierung, die zu einer Schwäche führt ist die Projektzeiterfassung der Mitarbeiter. Dabei stellte sich die Frage, was passiert, wenn
die Zuordnungen zu Projekten, Fachgruppen und Aufgabenkatalogen nicht vollständig durchgeführt wird, weil beispielsweise der Browser geschlossen oder ein anderer
Menüpunkt ausgewählt wird.
25
Ohne Betrachtung dieses Problems wären die eingegebenen Daten einfach verworfen worden, was im Fall eines Ausfalls, weil beispielsweise der Browser abstürzt,
sehr ärgerlich geworden wäre. Die Zeitverteilung kann u. U. etwas Zeit in Anspruch
nehmen und ein frustrierter Mitarbeiter, der seine Zuordnungen ein zweites Mal vornehmen muss, weil alle Daten verworfen wurden, wird sicherlich keine allzu gründlichen Angaben mehr vornehmen.
Nominalisierung:
Ein Beispiel für Nominalisierung ist folgende Anforderung:
Durch die Eingabe einer Exceltabelle vom Controller werden die absoluten Arbeitszeiten der Mitarbeiter in das System eingegeben.
Zur Überprüfung, ob es sich bei einem Substantiv um eine Nominalisierung handelt, kann, wie [Rup 02, S. 208 ff.] beschrieben ist, folgendermaßen vorgegangen
werden:
• ”Passt das Substantiv sinnvoll in die Phrase ’ein(e) andauernde(r) ...’ (im Sinne
von kontinuierlich)”, oder
• ”Beschreibt ein Substantiv etwas, das man nicht anfassen kann?”
Trifft mindestens eine der beiden Fragen auf ein Substantiv zu, so handelt es
sich um eine Nominalisierung. In diesem Fall treffen für das Wort ”Eingabe” sogar
beide Fälle zu, d. h., dieser Prozess sollte weiter hinterfragt werden. Bei genauerer
Untersuchung dieses Punkts stellte sich heraus, dass dieses Problem im Rahmen
dieser Arbeit nicht zufrieden stellend gelöst werden kann. Dies ist auch einer der
Gründe dafür, dass in jedem Fall eine manuelle Arbeitszeiteingabe für die internen
Mitarbeiter existiert.
3.2.2
Checklisten zur Überprüfung
Widersprüchliche Anforderungen:
1. Bei der Befragung des Stakeholders Projektmanagement ergab sich die Information, dass bei der Planung eines Projektes festgelegt wird, wann ein Projekt
gestartet wird. Anschließend wird es in eine Exceltabelle eingetragen, der Controller
wird informiert und redundant dazu wird dieses Projekt in das SAP-System eingegeben.
26
2. Eine Anforderung vom Stakeholder Abteilungsleiter war, dass Projekte auch
rückwirkend eingegeben werden sollten, da das Eintragen der Projekte eventuell vergessen werden konnte, und die Projektinformationen korrekt sein sollten.
3. Des Weiteren sollen Berichte, die sich auf Daten der Vergangenheit beziehen,
nicht verändert werden, wenn sich irgendwelche Daten geändert haben.
Die 1. Anforderung schließt aus, dass das Eintragen eines Projekts vergessen
werden kann, da die Zeiterfassung die vorhandene Exceltabelle des Stakeholders
Projektmanager ersetzen soll. Des Weiteren stellt die 1. Anforderung einen Widerspruch zur dritten dar, da die besagten Berichte beispielsweise auch eine Auflistung
aller aktuellen Projekte eines Monats enthalten, die bei einem rückwirkenden Eintragen verfälscht werden würden.
Die Konsequenz daraus ist, dass Projekte nur mit einem Projektstart angelegt
werden dürfen, der nicht in der Vergangenheit liegt.
Unnötige Anforderungen sind beispielsweise Anforderungen, die beschreiben, in
welchem Fall welcher Button wie gefärbt wird, wobei dieser Punkt ebenfalls abhängig
von den Möglichkeiten der verwendeten Implementierungstechnik ist. In ASP. NET
ist es beispielsweise kein Aufwand, Buttons in unterschiedlichen Farben darzustellen oder Tabellenspalten für bestimmte Benutzergruppen auszublenden. In anderen
Implementierungstechniken für Web-Applikationen ist dies nicht so ohne weiteres
der Fall. Dabei zeigt sich auch, dass Anforderungen niemals völlig unabhängig vom
Entwurf und von der Implementierung sind.
Folgende Aspekte können ebenfalls als Checkliste verwendet werden:
• Die Untersuchung der sprachlichen Schwächen aus Kapitel 3.2.1
• Die Struktur des Requirements Documents aus Kapitel 3.3
Da es den Umfang der Arbeit sprengen würde, wurde dieses Thema nicht weiter
vertieft.
3.3
3.3.1
Requirements Document
Systemmodelle
Gemäß Kapitel 2.3.3 werden im Folgenden die verwendeten Systemmodeltechniken
beschrieben.
Als statisches Modell wurde ein Klassendiagramm (siehe Abbilung 8) gewählt
und das in Kapitel 6.7.2 noch vorgestellte, Datenbankmodell. Wie bereits in der Einleitung (Kapitel 1.3) erwähnt wurde, soll die entwickelte Struktur einen Vergleich
27
Abbildung 8: Systemmodell: Klassendiagramm
der Datenbanktechniken ermöglichen. Aus diesem Grund kann das Klassendiagramm
nicht eins-zu-eins verwendet werden, dient aber zur Beschreibung der Entitäten und
ihrer Beziehungen.
Als dynamisches Modell wurden Statechart Diagramme verwendet. Diese beschreiben das Benutzerverhalten und die Möglichkeiten der Benutzeroberfläche. Die
Zustände bilden dabei jeweils einen Zustand der Benutzeroberfläche ab und die Transitionen beschreiben die Benutzeraktionen. Statechart Diagramme können zudem
geschachtelt werde, wodurch die jeweiligen Zustände Schritt für Schritt verfeinert
werden können. Durch die Schachtelung lassen sich Funktionsblöcke auf verschiedenen Detailliertheitsgraden darstellen.
Der Zustand AuthentificatedUser, wie in Abbildung 9 dargestellt, kann nur erreicht werden, wenn sich der Benutzer zuvor erfolgreich authentifiziert hat (siehe
Kapitel 5.6). Einschränkungen, welche die Benutzerrechte betreffen, werden nicht in
den Statechart Diagrammen, sondern direkt in den Requirements beschrieben (siehe
Kapitel 3.3.2). Befindet sich der Benutzer in einem bestimmten Unterzustand wie
beispielsweise Project, so hat er immer die Möglichkeit, durch Auswahl eines anderen
Menüpunktes den Zustand Project zu verlassen (beispielsweise durch Betätigen des
Buttons Mitarbeiterverwaltung - ButtonEmployeeClick ). Die Statechart Diagramme
wurden dabei bewusst einfach gehalten, beispielsweise wurden keine parallelen Kompositionen verwendet, um die Benutzermöglichkeit einfach erkennbar zu lassen und
28
Abbildung 9: Statechart Diagramm für die Menüführung
die Testfallgenerierung nicht zu erschweren. Durch den dargestellten Junction Point
(siehe schwarzen Punkt in Abbildung 9) können mehrere Transitionen zu einer zusammengefasst werden (siehe auch [Lin 01]).
Abbildung 10: Use Case Modell zur Beschreibung der drei Hauptfunktionalitäten
Das in Abbildung 10 dargestellte Use Case Diagramm soll aus einer sehr abstrakten Sicht zeigen, welches die generellen Funktionsblöcke sind. Die Akteure spiegeln
dabei nicht die Stakeholder wider, sondern sollen die drei generellen Benutzerrollen
beschreiben. Die Administratorrolle mit den Use Case ”System verwalten” beschreibt
die Funktionalitäten, die nötig sind, da keine Anbindung an das vorhandene SAPSystem möglich ist. Dieser Use Case enhält auch die Eingabe der absoluten Arbeitszeiten und die Projektverwaltung. Die Mitarbeiter ordnen ihre Arbeitszeiten den
Projekten, Fachgruppen und Aufgabenkatalogen zu. Die durch die Mitarbeiter und
den Administrator gesammelten Informationen können dann von einer Controllerrolle in Form von Berichten (Reports) ausgegeben werden (siehe auch [ReqDoc, 2.2
Produkt-Funktionen]).
29
3.3.2
Struktur eines Requirements
Wie in Kapitel 2.3.2 beschrieben ist, hat sowohl die rein natürlichsprachliche als
auch die rein formale Beschreibung ihre Nachteile. Um die Anforderungen leicht
verständlich, aber trotzdem vollständig zu beschreiben, wurden bestimmte Informationen der Anforderungen aus den Formulierungen extrahiert (siehe Abbildung 11
auf Seite 32). Die Anforderungsbeschreibung ist in diesem Fall frei von umständlichen Formulierungen, welche beispielsweise die Möglichkeiten der Benutzerführung
(durch die Statechart Referenz) oder die Benutzerrechte betreffen. Die einzelnen
Punkte werden unterschieden in zwingend erforderliche und optionale. Diese Punkte können ebenfalls als Checkliste verwendet werden (siehe Kapitel 3.2.2), um zu
überprüfen, ob die Anforderungen vollständig sind.
3.3.3
Struktur des Requirements Documents nach [IEEE830-1998]
Gemäß Kapitel 2.3 wurde das Requirements Document nach dem [IEEE830-1998]
Standard verwendet. Dieser besteht, wie in Abbildung 12 darstellt, aus drei Teilen:
Das erste Kapitel Einleitung gibt einen groben Überblick über das Produkt und
das Requirements Document. Im Abschnitt Zielsetzung wird beschrieben, warum
dieses Produkt benötigt wird (siehe Kapitel 3.1.1) und für welche Lesergruppen dieses Dokument geeignet ist. Definitionen, Akronyme und Abkürzungen helfen dabei,
eine gemeinsame ”Sprachbasis” zu definieren. Unterschiedliche Begriffe für gleiche
Dinge sollen damit vermieden werden. Der weitere Aufbau des Requirements Documents und die Struktur der einzelnen Anforderungen (siehe Kapitel 3.3.2) werden
im letzten Abschnitt beschrieben.
Das Kapitel Benutzercharakteristika beschreibt die Benutzergruppen, die im Kapitel Zielsetzung der Einleitung kurz vorgestellt wurden detaillierter. Eine genauere
Beschreibung der Stakeholder soll erklären, warum die Anforderungen genau so beschrieben wurden. Generelle Einschränkungen, Annahmen und Abhängigkeiten zu
definieren ist vor allem dann interessant, wenn die Anforderungen des 3. Kapitels
auf diese verweisen. Soll das System geändert werden, weil sich z. B. eine Abhängigkeit geändert hat, so wäre sofort erkennbar, welche Anforderungen davon betroffen
sind. Anforderungen, die vielleicht sinnvoll und nützlich sind, aber aus irgendwelchen Gründen nicht realisiert werden können, können im letzten Abschnitt des 2.
Kapitels aufgeschrieben werden, um nicht vergessen zu werden.
Vor allem das dritte Kapitel ist sehr dynamisch gehalten (siehe Kapitel 2.3). In
diesem Fall wurde die in Abbildung 12 dargestellte Form gewählt:
Der Punkt Schnittstellenbeschreibung ist noch offen und soll die Anbindung an
das SAP-System oder die Exceltabelle des Controllers beschreiben. Das in Kapitel
3.3.1 dargestellte Klassendiagramm und das Datenmodell befinden sich im Abschnitt
30
”Statische Systemmodelle”. Die eigentlichen Anforderungen werden durch zwei Sichten dargestellt (vgl. 2.4.4 und 3.1.5). Wie bereits in Kapitel 2.3.2 erwähnt wurde,
ist es schwierig, Anforderungen so zu beschreiben, dass sowohl ein Entwickler als
auch beispielsweise ein Projektmanager diese versteht und eindeutig interpretieren
kann. Aus diesem Grund wurden genau diese beiden Sichten dargestellt. Im Abschnitt ”Benutzeranforderungen” werden nur die Benutzerfunktionalitäten ohne alle
Sonder- und Ausnahmefälle beschrieben. Diese Sicht soll einen detaillierten Überblick über alle vorhandenen Funktionalitäten geben, ohne dass zu sehr ins Detail
gegangen wird. Für den Entwickler, der aus diesen Anforderungen eindeutig ableiten soll, was entwickelt werden soll, wird diese Sicht nicht ausreichen. Aus diesem
Grund werden im Abschnitt ”Benutzeranforderungen mit Systemanforderungen” die
einzelnen Anforderungen im Detail beschrieben.
3.4
Abschließende Worte zum Requirements Engineering
Wie schon im Kapitel 2.1 beschrieben wurde, wird beim Requirements Engineering
ein iteratives Vorgehen vorgeschlagen. Dabei ist es sehr wichtig, diese Reihenfolge
auch diszipliniert durchzuführen. Anforderungen, die geändert, aber nicht im Requirements Document aufgenommen wurden, und anschließend implementiert wurden,
verfehlen den Grundgedanken des Requirements Engineerings. Dabei kann es sehr
schnell geschehen, dass Anforderungen, Entwurf und Implementierung nicht mehr
konform zueinander sind.
Da in diesem Fall kein CASE-Tools (siehe Kapitel 3.1.5) verfügbar war, war es in
dieser Arbeit sehr mühselig, die Anforderungen aktuell zu halten. Die Anforderungen
wurden in einer Exceltabelle mit der in Kapitel 3.3.2 beschriebenen Struktur verwaltet. Über die Filterfunktion konnten nur sehr eingeschränkte Sichten (Viewpoints)
auf die Anforderungen vorgenommen werden. Für die Ausgabe in dem Requirements
Document wurde eine Serienbrieffunktion verwendet, die diese Anforderungen nach
Latex konvertiert hat, da diese Arbeit und das Requirements Document mit Latex
erstellt wurden. Folgeänderungen durch Referenzen der Anforderungen untereinander, eine Versionsverwaltung und eine etwas bessere Möglichkeit, verschiedene Sichten auf die Anforderungen zu erhalten, hätten die Arbeit wahrscheinlich sehr viel
weniger mühselig gemacht.
Wie an den Beispielen zu sehen ist, war das Problem bei der Analyse gar nicht so
sehr die Abbildung des Problems auf geeignete Modelle, sondern vielmehr die Frage,
was abgebildet werden soll.
Eine klare Beschreibung, die angibt, wie detailliert Requirements beschrieben
werden sollen, habe ich nicht gefunden. In [Som Saw 97, eigene Übersetzung, S. 6]
heißt es nur: ”Der Detailliertheitsgrad der Anforderungen hängt im wesentlichen von
der Praxis in ihrem Unternehmen ab.”
31
ID:
Jede Anforderung besitzt eine eindeutige Identität. Durch die verwendete
Punkt-Notation werden diese hierarchisch geordnet, d. h., Project.Insert.Valid
beschreibt den detaillierteren Fall, wenn das Anlegen eines Projekts (Project.Insert) aus beschriebenen Gründen nicht möglich ist.
Priorität:
Jede Anforderung besitzt eine der drei folgenden Prioritäten:
• A (zwingend erforderlich),
• B (wäre gut, aber muss nicht sein) oder
• C (”nice to have”)
Benutzerrecht (optional): Bedingungen sind meist mit Transitionen verbunden
und beschreiben all diejenigen Bedingungen, die sich nicht auf Möglichkeiten
der Benutzeroberfläche oder die Benutzerrechte beziehen.
Anforderung: In diesem Punkt werden die eigentlichen Anforderungen (Requirement) beschrieben.
Statechart-Referenz: Jeder Funktionsblock besitzt genau ein Statechart Diagramm. Jede Anforderung muss sich auf einen Zustand oder eine Transition
beziehen, die hier beschrieben wird.
Stakeholder: Jede Anforderung kommt von einem Stakeholder, der als Referenz
für die Anforderung gilt. Dieser kann sich von den Benutzerrechten unterscheiden, beispielsweise wenn Forderungen vom Auftraggeber für Mitarbeiterfunktionalitäten beschrieben werden.
Referenz (optional): Alle zusätzlichen Referenzen (siehe Kapitel x) werden hier
beschrieben. Aus zeitlichen Gründen wurde diese Spalte nicht vollständig ausgefüllt. Dieser Punkt stellt auch eine Erweiterung des Punktes Stakeholder
dar.
Beispiel (optional): Vor allem bei Berechnungen oder beschriebenen Einschränkungen können Beispiele unterstützend verwendet werden.
Anmerkung (optional): In diesem Punkt werden detaillierte Beschreibungen für
eine Anforderung, die keine neue Anforderung darstellt, oder Begründungen
für bestimmte Anforderungen beschrieben.
Abbildung 11: Aufbau eines Requirements
32
1. Einleitung
(a) Zielsetzung
(b) Produkt- und Anwendungsbereich
(c) Definitionen, Akronyme und Abkürzungen
(d) Referenzen
(e) Überblick zum restlichen Dokument
2. Generelle Beschreibung
(a) Produkt-Perspektiven
(b) Produktfunktionen
(c) Benutzercharakteristika
(d) Generelle Einschränkungen
(e) Annahmen und Abhängigkeiten
(f) Anforderungen für Weiterentwicklungen
3. Spezifische Anforderungen
(a) Schnittstellen im Detail
(b) Statische Systemmodelle
(c) Benutzeranforderungen
(d) Benutzeranforderungen mit Systemanforderungen
4. Anhänge
5. Index
Abbildung 12: Requirement Dokument nach [IEEE830-1998]
33
4
Konzepte von ASP.NET
4.1
4.1.1
Grundlagen
3-Tier-Architektur
Im Allgemeinen werden Web-Applikationen als 3-Tier-Architektur konzipiert, wie in
Abbildung 13 dargestellt ist.
Abbildung 13: 3-Tier-Architektur für Web-Applikationen
In einer 3-Tier-Architektur sind Client11 , Applikation und Datenbank voneinander getrennte Einheiten. Der Client kommuniziert nur mit dem Applikationsserver
(oft auch Businesslogik genannt), welcher wiederum mit einer Datenbank kommuniziert, d. h., der Client und die Datenbank kommunizieren niemals direkt miteinander.
Durch Senden einer parametrisierten Webseiten-Anfrage an den Server fordert der
Client vom Server eine Webseite an. Diese ist abhängig von der jeweiligen Anfrage. Für jede Benutzeraktion (beispielsweise das Betätigen eines Buttons) wird eine
solche Anfrage an den Server gesendet (siehe auch [Sch 02, S. 9 ff.]).
4.1.2
.NET - Framework
Eine verhältnismäßig neue Entwicklungsform für Web-Applikationen ist ASP.NET.
ASP.NET ist ein Bestandteil des .NET Frameworks, wie in Abbildung 14 dargestellt.
In [MSDN .NET Framework FAQ 01, eigene Übersetzung] wird das .NET Framework definiert als, ”eine integrierte Windowskomponente, zum Ausführen und
Entwickeln von Applikationen [..] der nächsten Generation. Das .NET Framework
ist sprachenunabhängig und stellt eine umfangreiche Klassenbibliothek zur Verfügung [(Base Class Library)].”
Auf dem (Windows-)Betriebssystem ist eine Common Language Runtime aufgesetzt, die, ähnlich der JAVA Virtual Maschine, ein Programm nicht direkt ausführt,
11
Der Client der Web-Applikation ist immer der Web-Browser.
34
Abbildung 14: Das .NET Framework
sondern es erst bei der ersten Verwendung in Maschinencode übersetzt. Die Programmiersprache, die in der Zeiterfassung verwendet wurde, ist C# (siehe Kapitel
4.1.4), obwohl die Festlegung einer Programmiersprache im .NET Framework nicht
unbedingt nötig ist, da über die Common Language Specification die verschiedenen
Klassen in verschiedenen Programmiersprachen entwickelt und beliebig miteinander
kombiniert werden können. Für die Web-Applikation ist vor allem ASP.NET wichtig.
Die Konzepte von ASP.NET werden in Kapitel 4.1.5 genauer beschrieben.
4.1.3
Businessobjekte
In .NET gibt es zwei Möglichkeiten, Gruppen von Klassen zu Komponenten oder
Businessobjekten zusammenzufassen (vgl. dazu auch [Mös 03]).
Assemblies:
Assemblies sind wiederverwendbare Programmpakete, die in einer physikalischen
Datei abgelegt sind und von anderen Applikationen verwendet werden können. Sie
sind in der Windowswelt sozusagen eine Weiterentwicklung der Dynamic Linked Librarys (DLL). Im Vergleich zu JAVA sind sie eng verwandt mit den JAR-Files.
Namespaces:
Namespaces sind ähnlich zu den Packages in JAVA. Im Gegensatz zu JAVA kann
eine Datei aber mehrere Namespaces besitzen oder sich ein Namespace über mehrere
Dateien erstrecken.
4.1.4
Die Programmiersprache C#
Parallel zum .NET-Framework wurde von Microsoft eine neue Programmiersprache mit dem Namen C# (gesprochen: ”See Sharp”) entwickelt. C# besitzt sehr viel
Ähnlichkeit mit JAVA und C++, aber auch einige neue Konzepte, die im Folgenden
35
erklärt und im Entwurf in Kapitel 5 verwendet werden.
Properties
Im [NetLexikon] wird ein Property (Eigenschaft) als eine Sicht auf ein Attribut
bezeichnet. Properties ersetzen die ”Getter”- und ”Setter”-Methoden und werden
wie Attribute einer Klasse verwendet, wie in Abbildung 15 an einem Beispiel gezeigt
wird. Die Konsistenzprüfung in dem Property Proration gewährleistet, dass das
Attribut immer kleiner als 100 ist.
(1) private string m Proration;
(2)
public string Proration {
(3)
get{ return this.m Proration; }
(4)
set {
(5)
if( value < 100 ) throw new Exception( ”Fehlermeldung” );
(6)
else this.m Proration = value;
(7)
}
...
Proration = 142; // wirf eine Exception
Abbildung 15: Beispiel für die Verwendung von Properties
Indexer
Ähnlich zu dem Konzept der Properties sind die Indexer. Diese erlauben es, auf
ein Objekt wie auf ein Array zuzugreifen. Indexer werden durch das Schlüsselwort
this definiert. Abbildung 16 zeigt eine Klasse Manager, die einen Indexer enthält.
(1)
(2)
(3)
(4)
(5)
(6)
...
(7)
(8)
(9)
public class Manager {
PersistentObject this [int id ] {
get { /* Gibt das PersistentObject id zurück */ }
set { /* Setzt das PersistentObject id */ }
}
}
Manager m = new Manager();
m[0] = new PersistentObject();
Persistentobject o = m[0];
Abbildung 16: Beispielcode für die Verwendung eines Indexer
Eventhandler
Ein Event ist eine Nachricht, die von einem Objekt gesendet wird, um das Auftreten einer Aktion zu signalisieren. Sie wird von einem Sender ausgelöst und von
einem Empfänger empfangen. Der Empfänger muss sich dafür beim Sender anmelden, was über ein Delegate passiert. In . NET wird dafür ein eigener Typ mit dem
36
Namen event zur Verfügung gestellt, bei dem ein Empfänger sich durch Übergeben
einer Methode (Delegation) anmelden kann. Wenn das Event eintritt bzw. gefeuert wird, werden die an dem Event angemeldeten Methoden aufgerufen (siehe auch
[Mös 03, Kap. 10]).
Sichtbarkeiten
In C# gibt es neben public, protected und private noch eine weitere Sichtbarkeit,
die durch das Schlüsselwort internal gekennzeichnet ist. Diese drückt aus, dass ein
Mitglied einer Klasse nur in derselben Assembly sichtbar ist. Im Klassendiagramm
wird diese Sichtbarkeit durch ein ∼ dargestellt.
4.1.5
ASP.NET Page-Framework
Microsoft definiert das ASP. NET Page Framework ”als ein Programmierframework,
das auf einem Webserver läuft und dynamisch Webseiten erzeugt und verwaltet.
Diese Webseiten werden Webforms genannt und können im Visual Studio entwickelt und implementiert werden. ... Das ASP .NET Page Framework schafft eine
Abstraktion der traditionellen Client-Server Kommunikation, die es ermöglicht, eine
Web-Applikation mit den traditionellen objektorientierten und eventbasierten Programmiertechniken zu entwickeln” ([MSDN ASP.NET, eigene Übersetzung]).
Eine Webform besteht aus zwei Teilen, die im Folgenden erklärt werden: visuelle
Elemente, die das Aussehen der grafischen Benutzeroberfläche (siehe Kapitel 4.3)
beschreiben, und die dazugehörige Programmlogik (siehe Kapitel 4.2).
4.2
Codebehind-Technologie
Verbunden wird eine Webform mit ihrer Codebehind-Klasse durch eine so genannte
Page-Direktive. Die Codebehind-Klasse, wie in Abbildung 17 dargestellt, ist eine
Klasse, die von der Page abgeleitet werden muss. Die Klasse Page stellt Schnittstellen zur Verfügung, um das gewünschte Verhalten der Webform zu implementieren.
Der Einstiegspunkt in eine Codebehind-Klasse ist die Methode OnInit. In C#
müssen Methoden, die überschrieben werden können, explizit mit dem Schlüsselwort
virtual, und wenn sie überschrieben werden, explizit mit dem Schlüsselwort override
gekennzeichnet werden.
In dem Beispiel von Abbildung 17 werden den Events Load und PreRender jeweils Methoden zugeordnet, die beim Eintreten der entsprechenden Events ausgeführt werden. In Kapitel 4.5 werden der Lebenszyklus und die möglichen Events
eines Page-Objekts noch genauer beschrieben.
37
Abbildung 17: Beschreibung der Codebehind-Technologie
4.3
Webforms
4.3.1
Einleitung
Eine Webform ist eine Webseite (HTML-Seite) mit einem HTML-Formular, die neben HTML-Elementen und einem HTML-Formular so genannte Server Controls enthält. Server Controls sind grafische Objekte mit Methoden, Properties und Events.
Der in dem HTML-Attribut id angegebene Name definiert den Namen des Properties in der entsprechenden Codebehind-Klasse, d. h., auf der Clientseite werden
HTML-Elemente angezeigt und in der Codebehind-Klasse erscheinen diese als ”echte
Objekte”. Durch diesen Mechanismus wird die in Kapitel 4.1.5 beschriebene Abstraktion realisiert.
Die Server Controls werden unterschieden in HTML Server Controls und Web
Server Controls.
4.3.2
HTML Server Controls
HTML Server Controls repräsentieren HTML-Elemente. Die Attribute der HTMLElemente bilden die Attribute der HTML Server Controls in der Codebehind-Klasse.
Wird beispielsweise in der Codebehind-Klasse ein Attribut eines HTML Server Controls geändert, so erscheint beim Client das HTML-Element mit dem geänderten
Attribut.
38
Abbildung 18: Zusammenhang von HTML und Server Controls
Abbildung 18 soll diese Funktionsweise und den Zusammenhang von HTMLElementen und Properties erklären. Der Client schickt an den Server eine HTTPAnfrage, in der er eine Webseite anfordert. Das ASP .NET Page Framework wandelt
die HTML-Elemente in HTML Server Controls Objekte um. Die Codebehind-Klasse
besitzt dann für jedes HTML Server Control ein Property, welches den gleichen Namen besitzt wie das Attribut id des HTML-Elements.
Die Properties können dabei beliebig geändert werden. Nachdem die Anfrage
abgearbeitet wurde, wandelt das ASP .NET Page Framework die Server Controls
(mit den geänderten Attributen) in HTML um und schickt das erzeugte HTMLDokument an den Client zurück.
Des Weiteren kann ein Server Control Events besitzen. Ein Beispiel ist das
HTMLButton Server Control. Dieser besitzt ein Event ServerClick, was ausgeführt
wird, wenn der entsprechende Button auf der Clientseite betätigt wurde.
Ein weiteres Konzept kann durch den Zustatz runat=”server” im HTML Server
Control realisiert werden. Dieser Zusatz bedeutet, dass auf dem Server eine Instanz
des entsprechenden Objekts gehalten wird, welche den Zustand des entsprechenden
Objekts enthält. In einem ViewState12 wird zu jedem Objekt, was als runat=”server”
definiert wurde, eine Referenz abgelegt, die dieses Objekt auf dem Server identifiziert. Damit besteht die Möglichkeit, dass dem Server nur mitgeteilt wird, was an
einem Objekt geändert wurde, ohne das komplette Objekt bzw. alle Attribute zu
übertragen.
4.3.3
Web Server Controls
Die zweite Form von Server Controls sind die Web Server Controls. Während die
HTML Server Controls die HTML-Elemente repräsentieren, ist die Vorgehensweise bei den Web Server Controls genau entgegengesetzt. Die Web Server Controls
beschreiben komplexe grafische Objekte und die Umwandlung in HTML kann sich
12
Ein ViewState ist eine versteckte Variable, die in einer Webform enthalten ist und zusätzliche
Informationen für den Server enthält.
39
über mehrere HTML-Elemente erstrecken.
Ein spezielles Web Server Control ist der PlaceHolder, der als Container innerhalb einer Webform verwendet wird. Dieser besitzt eine Methode, um ihn in weitere
Server Controls zu laden. Dadurch können dynamisch Inhalte in einer Webform
gesetzt werden. Web Server Controls, die mindestens einen PlaceHolder besitzen,
werden im Folgenden auch als Templates bezeichnet.
Neben den vordefinierten Server Controls besteht auch die Möglichkeit, eigene
Server Controls zu entwickeln. Diese werden User Controls genannt. In Kapitel 5.4.5
wird ein Beispiel für die Entwicklung eines User Controls beschrieben.
4.4
Zustandsmanagement
In einer Web-Applikation kommuniziert der Client über das zustandslose HTTPProtokoll mit dem Server. Gleiche Serveranfragen von verschiedenen Clients werden
nicht unterschieden. Nach der Verarbeitung der Anfrage werden alle Verbindungsdaten verworfen. Bei einer Web-Applikation ist es aber nötig, dass Zustandsinformationen verwaltet werden. ASP.NET bietet dafür verschiedenste Möglichkeiten, die
im Folgenden beschrieben werden.
Versteckte Formularfelder:
Die einfachste Möglichkeit, Zustandsinformationen zu halten, ist es, diese mit
jeder Anfrage an den Server in versteckten Formularfeldern mitzuschicken. Die Methode RegisterHiddenField in der Klasse Page bietet die Möglichkeit, versteckte
Formularfelder zu definieren, die beim Erzeugen der HTML-Seite mit angelegt werden. Die mitgeschickten Zustandsinformationen sind allerdings im HTML-Code in
Klartext sichtbar, was vor allem bei sensiblen Daten sehr nachteilig ist.
ViewState:
Jede Webform enthält ein verstecktes HTML-Element mit dem Namen VIEWSTATE. In der Page-Klasse wird dieser Viewstate durch ein Property repräsentiert.
Auf dieses Property kann in der Codebehind-Klasse zugegriffen werden. Der Vorteil
dieser Variante, im Vergleich zu den versteckten Formularfeldern, ist, dass die Daten nicht mehr als Klartext sichtbar sind. Allerdings müssen die Zustandsdaten bei
dieser Variante immer noch bei jeder Serveranfrage mitgesendet werden.
Session:
Eine Session ist der Zeitraum vom ersten Aufruf einer Webseite bis zum Schließen des Webbrowsers. Allerdings kann eine Session auch vorher vom Server beendet
40
werden (beispielsweise wenn ein Timeout abgelaufen ist) oder über das Schließen
des Webbrowser hinaus gültig sein, wenn die Sessiondaten im Cookie gespeichert
werden. Hierfür bittet die Klasse Page das Property Session an. In diesem Property können Daten, die abhängig von einer Session sind, verwaltet werden, d. h., die
Zustandsinformationen werden nicht bei jeder Anfrage mit übermittelt.
Application:
Informationen können auch über die gesamte Lebenszeit einer Applikation verwaltet werden. Eine Applikation startet, wenn die erste Anfrage an den Server gesendet wird, und endet, wenn die Konfigurationsdaten geändert oder der Serverprozess
beendet, wird. Hierfür bietet die Page-Klasse ein Property mit dem Namen Application an.
4.5
Lebenszyklus eines Page-Objekts
Um zu verstehen, welche Schnittstellen das ASP.NET Page Framework anbietet,
wird in diesem Kapitel der Lebenszyklus eines Page Objekts beschrieben, d. h. was
passiert zwischen einer Serveranfrage und dem anschließenden Senden der HTMLSeite (vgl. Kapitel 4.1.1).
Wie bereits erwähnt wurde, ist das zentrale Konzept von ASP.NET die Klasse
Page. Bei einer Serveranfrage bzw. Anfrage an einer Webform wird eine Instanz der
dazugehörigen Codebehind-Klasse erzeugt. Den verschiedenen Events können durch
Überschreiben der Methode Init (vgl. Kapitel 4.2) eigene Methoden übergeben werden, die im Folgenden kurz beschrieben werden (vgl. [Esp 04]).
In Abbildung 19 ist der Lebenszyklus eines Page-Objekts dargestellt.
Nachdem die OnInit-Methode durch das Event Init aufgerufen wurde, werden
die übergebenen Variablen ausgewertet. Dies sind zum einen der Viewstate und zum
anderen die durch die http-Anfrage übergebenen Variablen. Der Viewstate enthält
Referenzen auf die Server Controls, die durch runat=”server” gekennzeichnet wurden. Die Server Controls dieser Referenzen werden geladen. Anschließend werden
die durch den Post-Mechanismus übertragenen Formulardaten ausgewertet. Nach
Abschluss dieser Phase besitzen die Objekte auf dem Server den gleichen Zustand
wie auf dem Client.
Anschließend wird das Event Load aufgerufen. Dieses Event ist dafür gedacht,
benutzerdesfiniertes Initialisieren vorzunehmen. Das Laden der User Controls in die
Templates ist ein Beispiel dafür. Des Weiteren können Attribute initialisiert werden.
Diesem Event wird üblicherweise eine Methode Page Load übergeben.
41
Abbildung 19: Lebenszykus eines Page-Objekts
Die Benutzeraktionen (Betätigen eines Buttons oder das Ändern einer Auswahl
in einer Dropdownliste, sofern dies definiert wurde) werden in der nächsten Phase
ausgewertet. Den Events der Server Controls können zuvor Methoden übergeben
worden sein, die in dieser Phase ausgewertet werden. Wurde eine Seite angefragt,
weil ein Benutzerevent ausgeführt wurde, so spricht man auch von Postback. In der
Page-Klasse steht hierfür ein Property zur Verfügung, mit dem geprüft werden kann,
ob eine Seite durch einen Postback aufgerufen wurde. In diesem Fall müssen dann
eventuelle Initialisierungen nicht mehr vorgenommen werden.
Bevor die HTML-Seite zusammengebaut wird, wird das Event PreRender geworfen. Dieses Event wird nach den Benutzeraktionen ausgeführt und kann beispielsweise abhängig von diesen bestimmten Ausgaben erzeugen. Die übliche Methode für
dieses Event ist eine Methode mit dem Namen PreRender.
Im letzten Schritt wird der ViewState zusammengesetzt, d. h., die in dem Property ViewState enthaltenen Daten werden als String kodiert, die HTML-Seite wird
zusammengesetzt und die zuvor angeforderten Ressourcen werden freigegeben.
42
5
5.1
Architektur und Entwurf der Webapplikation
Einleitung
Im objektorientierten Entwurf wird für das aus der Analyse spezifizierte System ein
abstraktes Implementierungskonzept erstellt. Der Entwurf sollte die Analyse erweitern und unabhängig von der Implementierung sein (siehe auch [Bit Koc 00, S. 47]).
In diesem Fall war dies allerdings in der Form nicht möglich. Die Struktur der
Zeiterfassung soll neben den Benutzermöglichkeiten einen Vergleich von den in der
Einleitung vorgestellten Datenbanktechniken ermöglichen. Dieser Aspekt war bei
der Analyse nicht relevant, muss aber im Entwurf berücksichtigt werden. Aus diesem Grund kann auch das in Kapitel 3.3.1 dargestellte Klassendiagramm im Entwurf
nicht erweitert werden.
Zu diesem Zweck wurde eine Framework entwickelt, was diesen Vergleich ermöglichen soll. Die Idee für diese Struktur stammt von einem Persistenz Framework, das
in der Firma Francotyp Postalia entwickelt wurde. Die Architektur der Zeiterfassung
wird in Kapitel 5.2 beschrieben. In Kapitel 5.3 wird detaillierter auf die Struktur
des entwickelten Frameworks eingegangen.
Ein weiterer Punkt für das geänderte Vorgehen ist der, dass die Zeiterfassung
das ASP .NET Framework verwenden soll. Hierbei können nur die vordefinierten
Schnittstellen verwendet werden, was beim Entwurf ebenfalls berücksichtigt werden
muss. Dieser Aspekt muss vor allem bei dem Entwurf des Web-Interfaces betrachtet
werden. Das Web-Interface bildet die Schnittstelle zwischen Benutzer und Businesslogik (siehe Kapitel 5.4).
Das .NET Framework bietet zwar ein Konzept für das Zustandsmanagement
(vgl. Kapitel 4.4) an, aber stellt keine Technik zur Verfügung, um die Navigation
durch die Webseiten zu steuern. Der Entwurf für die angewandte Technik des Zustandsmanagements und die Navigation werden in Kapitel 5.5 beschrieben.
Ein weiteres Problem, was gelöst werden muss, ist die Authentifizierung der Benutzer und die Definition der Zugriffsmöglichkeiten. In Kapitel 3.2 wurde beschrieben, welche Benutzerrollen existieren und welche Möglichkeiten diese haben. Hierfür
wird der integrierte Windows Authentifizierungsmechanismus des .NET Frameworks
verwendet. Dieser wird in Kapitel 5.6 dargestellt.
Abgeschlossen wird das Kapitel Entwurf mit einem Überblick über das gesamte
System (siehe Kapitel 5.7). Dort werden die vorgestellten Entwürfe zusammengeführt. Außerdem werden in diesem Kapitel einige weitere Probleme, wie beispielsweise die Nebenläufigkeit, kurz angesprochen.
43
5.2
Architektur
Die Zeiterfassung besteht, wie in Abbildung 20 dargestellt, aus fünf Komponenten.
Jede Komponente ist gleichzeitig ein eigenes Assembly und besitzt einen eigenen
Namespace (vgl. Kapitel 4.1.3).
Abbildung 20: Struktur der Komponenten
Die Komponente ProjectManagement bildet die Schnittstelle zwischen Benutzer
und Businesslogik. Nach dem Model View Controller Design Pattern nimmt diese
Komponente die Rollen Controller und View ein und realisiert das Web-Interface.
Im Kapitel 5.4 wird die Struktur detaillierter beschrieben. Die Businesslogik besteht
aus den folgenden zwei Komponenten:
1. Die Komponente ProjectManagement.Core ist ein Framework, welches persistente Objekttypen und ihre Managerklassen als abstrakte Klassen definiert
(siehe Abbildung 20). Managerklassen sind Klassen, die persistente Objekte eines bestimmten Typs verwalten. Für jede Entität existiert ein Typ eines persistenten Objekts und ein dazugehöriger Manager. Diese beiden stehen
miteinander in Beziehung. Der detaillierte Aufbau dieses Frameworks wird in
Kapitel 5.3 beschrieben.
2. Die konkrete Implementierung mit der jeweiligen Datenbanktechnik wird in der
spezifischen Komponente (siehe Abbildung 21) realisiert. Für jede Managerklasse und jedes persistente Objekt muss eine spezifische (abgeleitete) Klasse
definiert werden, welche die definierten abstrakten Methoden implementiert.
44
Komponente: ProjectManagement. Datenbanktechnik
Realisierung
Core.Relational
relational
s. Kapitel 6
Core.ObjectRelational
objektrelational
Theorie in Kapitel 7
Core.ObjectOriented
objektorientiert
Idee
Abbildung 21: Übersicht der spefizischen Komponenten
5.3
5.3.1
Persistenz-Framework
Einleitung
Das entwickelte Framework wird als Persistenz Framework bezeichnet, da es persistente Objekte verwaltet. In dem ”echten” Persistenz-Framework (siehe Kapitel 5.1),
was die Motivation für diese Struktur war, werden die entsprechenden Datenbankoperationen automatisiert, d. h., über Reflexion werden die Attribute der Objekte
ausgelesen und über Umwandlungsroutinen in Datenbankoperationen umgewandelt.
Da das ”echte” Persistenz-Framework ziemlich komplex in seiner Struktur und Anwendung ist, wurde, wie bereits erwähnt, nur die Idee übernommen.
Ziel der Zeiterfassung ist die Verwaltung von persistenten Objekten verschiedenster Typen, wie beispielsweise Projekte, Mitarbeiter oder Fachgruppen. Die benötigten Operationen lassen sich dabei in zwei Arten unterscheiden:
1. Operationen, die direkt an einem persistenten Objekte ausgeführt werden, um
beispielsweise den Zustand eines Objekts zu ändern (siehe PersistentObject in
Abbildung 22), und
2. Operationen, die eine bestimmte Menge von Objekten eines bestimmten Typs
zurückliefern oder auf einer Menge von Objekten eines bestimmten Typs ausführen werden. Ein Beispiel ist eine Anfrage nach allen Projekten, die keine
Fachgruppen besitzen. Diese Operationen werden in den bereits erwähnten
Managerklassen realisiert (siehe PersistentManager in Abbildung 22).
Die Klassen ProjectManagerImpl, ControllerImpl und ProjectImpl in Abbildung
22 zeigen ein Beispiel für Klassen, die in einer der drei spezifischen Komponenten,
wie beispielsweise ProjectManagement.Core.Relational, realisiert werden.
Anhand des Beispiels Project und ProjectManager wird im Folgenden die abstrakte Managerklasse (PersistentManager, siehe Kapitel 5.3.3) mit ihren spezifischen Managerklassen beschrieben. Mit spezifischen Managerklassen sind in diesem
Fall Klassen gemeint, die in der Komponente ProjectManagement.Core enthalten
und von PersistentManager abgeleitet sind, wie in Abbildung 22 die Klasse ProjectManager. Diese Klassen sind abstrakt und müssen in den konkreten Managern
implementiert werden. Konkrete Manager sind Klassen, die von den spezifischen
Managerklassen abgeleitet sind und in der konkreten Komponente (siehe Abbildung
45
Abbildung 22: Struktur des Persistenz Frameworks am Beispiel Projekt
21) die jeweiligen Funktionalitäten implementieren.
Die Formulierung spezifisch und konkret wird auch für persistente Objekte (PersistentObject, siehe Kapitel 5.3.3) und die Schnittstelle (Controller, siehe Kapitel
5.3.4) zur Komponente ProjectManagement verwendet.
Abgeschlossen wird das Kapitel in 5.3.5 mit einem Überblick der vorhandenen
persistenten Objekte der Zeiterfassung.
5.3.2
Persistenz Manager
Erzeugt werden persistente Objekte durch ein Factory Pattern, welches in der in
Abbildung 22 dargestellten Struktur enthalten ist. In Abbildung 23 sind die Rollen des Factory Patterns und die zugehörigen Klassen des entwickelten Frameworks
dargestellt.
Die Methode CreateObject im PersistentManager hat die Rolle der Methode
FactoryMethode im Factory Pattern. In der konkreten Implementierung der Managerklasse erzeugt diese Methode eine Instanz des konkreten PersistentObjects.
Das Erzeugen eines solchen Objekts darf nur über diese Methode erfolgen. Dadurch
”kennt” jeder Manager den Typ seines persistenten Objekts (siehe Abhängigkeit persistentObject in Abbildung 22).
46
Klassen im Factory Pattern
Klassen im Persistenz-Framework
Creator
PersistentManager
ConcreteCreator
spezifische Implementierung der Managerklasse
Product
PersistentObject
ConcreteProduct
spezifische Implementierung des PersistentObjects
Abbildung 23: Rollen des Factory Patterns im Persistenz-Framework
Der Indexer (vgl. Kapitel 4.1.4) im PersistentManager ermöglicht es, einen spezifischen PersistentManager wie ein Array zu verwenden. Jedes konkrete persistente
Objekt besitzt eine Identität in Form einer Zahl. Im Indexer kann anhand dieser
Zahl ein konkretes Objekt ermittelt werden. Existiert kein Objekt zu der übergebenen Zahl, so wird ein Null Pointer zurückgeliefert. Der Indexer ist abstrakt und
muss in der konkreten Komponente bzw. im konkreten Manager realisiert werden.
Der Indexer erlaubt nur lesende Zugriffe, da das Einfügen, Ändern und Löschen von
persistenten Objekten an den persistenten Objekten selber durchgeführt wird.
Wenn ein Objekt mit der Identität 42 existiert, dann würde der Aufruf Controller.ProjectManager[42] dieses Objekt zurückliefern.
Die Methoden Insert, Update und Delete werden im PersistentManager definiert
und müssen in der konkreten Implementierung der Managerklasse realisiert werden.
Der Zugriff auf diese Methode erfolgt aber über die persistenten Objekte. In Kapitel
5.3.3 wird der Ablauf genauer beschrieben.
Durch die Methode LoadArrayList wird eine Array mit allen Objekten des jeweiligen Typs zurückgeliefert. In den spezifischen Managerklassen können weitere abstrakte Methoden definiert werden, die beispielsweise die Ergebnismenge einschränken oder andere Funktionalitäten auf der Menge der persistenten Objekte definieren.
Die Methode GetNewProjectNumber (siehe Abbildung 22) ist ein Beispiel für
eine weitere Methode. Abhängig vom Projekttyp wird durch diese eine neue vorgeschlagene Projektnummer ermittelt (vgl. Kapitel 3.2.1 das Beispiel Tilgung).
5.3.3
Persistente Objekte
Wie bereits in Kapitel 5.3.2 erwähnt wurde, ist das Einfügen, Ändern und Löschen
eine Eigenschaft des persistenten Objekts. Diese Methoden leiten die Anfragen an
ihren jeweiligen Manager (siehe Insert, Update und Delete in Abbildung 22 auf Seite
46 in der Klasse PersistentObject).
In Abbildung 24 ist der Ablauf für das Einfügen eines persistenten Objekts dar47
Abbildung 24: Einfügen eines persistenten Objektes
gestellt. Die Methode CreateObject erzeugt lediglich eine neue Instanz des jeweiligen
Objekts mit einer Verbindung zu seinem Manager. Persistent im eigentlichen Sinne,
d. h. dass diese Daten beispielsweise auch in der Datenbank abgelegt werden, ist dieses Objekt in diesem Zustand noch nicht. Erst durch Aufrufen der Methode Insert
werden diese Objekte in der entsprechenden Datenbank hinzugefügt. Diese Methode
liefert ein Boolean zurück. Im Falle eines Fehlers wird false zurückgeliefert. Durch
das Property CurrentError wird in diesem Fall die Fehlermeldung ermittelt.
Wie bereits erwähnt wurde, besitzt jedes persistente Objekt eine Identität in
Form einer Zahl. In Kapitel 6.2.2 wird noch auf die Schwierigkeiten bei diesem Vorgehen eingegangen. Darüber hinaus besitzt jedes persistente Objekt einen Namen
(siehe Property Name in Abbildung 22). Die Realisierung dieses Namens kann in
den jeweiligen konkreten persistenten Objekten unterschiedlich aussehen. Bei einem
Mitarbeiter ist dieser beispielsweise eine Kombination aus Vor- und Nachname, während dieser für ein Projekt der Name des Projektes ist.
Die Informationen, die in einem spezifischen persistenten Objekt gespeichert werden, lassen sich in zwei Arten unterscheiden:
Zum einen sind dies einfach Daten, die in Form von Properties definiert werden.
Beispiele hierfür im Projekt sind der Projektstart (statedDate) oder die Bemerkung
zum Projektabschluss (finishComment).
Die zweite Art von Informationen sind Abhängigkeiten zu anderen persistenten
Objekten, wie beispielsweise ein Projektleiter (projectLeader ) in einem Projekt, der
ein Mitarbeiter (Employee) ist. Ein Überblick aller persistenten Objekte und ihrer
Abhängigkeiten zueinander wird in Kapitel 5.3.5 dargestellt.
In den spezifischen persistenten Objekten können weitere Methoden definiert
werden. Wie in Abbildung 22 auf Seite 46 zu sehen ist, besitzt die Klasse Project
48
eine Methode Close, welche ein Projekt mit einem Datum und einer Bemerkung zum
Abschluss beendet. Ab dem definierten Datum ist das Projekt in der Projektliste
nicht mehr sichtbar und kann nur noch über die Berichte angezeigt werden.
Die Funktionalitäten für die prozentuale Zeitverteilung der Mitarbeiter auf die
Projekte wurden als Methoden des Projektes definiert. Ähnlich zu dem Einfügen,
Ändern und Löschen eines Objekts werden diese Methoden auf dem jeweiligen Objekt aufgerufen und in dem entsprechenden Manager implementiert.
5.3.4
Die Klasse Controller
Bisher wurden nur die Managerklassen und ihre persistenten Objekte beschrieben.
In diesem Abschnitt geht es darum, diese zusammenzuführen und eine Möglichkeit
zur Initialisierung des Frameworks zu geben. Die dafür verantwortliche Klassen sind
die Klassen Controller und ControllerImpl (siehe Abbildung 22 auf Seite 46).
Abbildung 25: Die Klasse Controller mit zwei Beispielmanagern
Die Klasse Controller besitzt zu jeder abstrakten Managerklasse einen Property
(siehe Abbildung 25). Die Komponente ProjectManagement (siehe Abbildung 22)
kann über den Controller auf diese Properties der jeweiligen Manager zugreifen.
Der Konstruktor der Klasse Controller ruft eine abstrakte Methode Init auf. Um
das Framework zu initialisieren muss von der Klasse Controller eine abgeleitete
Klasse definiert werden (ControllerImpl ), welche die Methode Init implementiert. In
dieser Methode werden Instanzen der konkreten Managerklassen erzeugt und an die
49
Properties bzw. an die dahinter liegenden Attribute gebunden. Durch eine Instanz
dieser abgeleiteten Klasse stehen dem Anwender - in diesem Fall der Komponente
ProjectManagement - alle Manager zur Verfügung.
5.3.5
Zusammenfassung und Übersicht über alle persistenten Objekte
Abhängig von der jeweiligen Datenbanktechnik wird eine Komponente erstellt, die
das entwickelte Framework verwendet. Dieses Framework definiert für jede Entität
ein Paar aus (persistenten) Managern und persistenten Objekten. In diesen Klassen
werden abstrakte Methoden definiert, die jeweils in die konkreten Klassen implementiert werden. Die Klasse Controller besitzt für jeden Manager einen Property, auf
den die Komponente ProjectManagement (also das Web-Interface) zugreifen kann.
Initialisiert wird das Framework durch eine konkrete Controllerklasse, welche konkrete Instanzen der Managerklassen an die Properties binden.
Einfügen, Ändern und Löschen von persistenten Objekten geschieht über Methoden an den Objekten selber, während Operationen, die sich auf Mengen von
persistenten Objekten beziehen, in den Managern aufgerufen werden.
Die beiden in Abbildung 25 dargestellten Managerklassen haben noch eine weitere Bedeutung. Die Arbeitszeiten der Mitarbeiter und die prozentualen Verteilungen dieser auf Projekte, Fachgruppen und Aufgabenkataloge sind abhängig von der
Kalenderwoche. Beim Starten einer Session (siehe Kapitel 4.4 auf Seite 40) müssen
die Kalenderwocheneinträge in der jeweiligen Datenbank aktualisiert (UpdateWeeks)
werden. Dieses Thema wird in Kapitel 5.5.2 noch beschrieben. Die Klasse Employee
besitzt außerdem eine Methode SelectEmployeeByAccount, die abhängig von einem
übergebenen Account einen Mitarbeiter zurückliefert. Die Problematik mit der Authentifizierung der Mitarbeiter wird in Kapitel 5.6 auf Seite 60 noch beschrieben.
In Abbildung 26 ist die Struktur der persistenten Objekte mit ihren Abhängigkeiten dargestellt.
Wie an dieser Abbildung zu sehen ist, können erst die konkreten persistenten Objekte auf die jeweils abhängigen persistenten Objekte zugreifen, d. h., diese müssen in
jeder konkreten Komponente implementiert werden. Ein weiteres Problem stellt die
fehlende Vererbung dar. Dadurch, dass jedes persistente Objekt direkt oder indirekt
von PersistentObject abgeleitet werden muss, besteht keine Möglichkeit, Vererbung
in den persistenten Objekten in der konkreten Komponente zu verwenden.
50
Abbildung 26: Klassendiagramm der persistenten Objekte
5.4
5.4.1
Entwurf des Web-Interfaces
Einleitung
Im Folgenden wird das Web-Interface beschrieben. In der Komponentenstruktur aus
Abbildung 20 in Kapitel 5.2 ist dies die Komponente ProjectManagement. Die Zeiterfassung besteht aus einer einzigen Webform und einer dazugehörigen CodeBehind
Klasse, die in Kapitel 5.4.2 beschrieben wird. Eine Web-Applikation besitzt einige
Besonderheiten im Vergleich zu einer nicht Web-Applikation, die beim Design berücksichtigt werden müssen. Diese werden in Kapitel 5.4.3 aufgezeigt.
Wie bereits in Kapitel 5.2 beschrieben wurde, werden in der Zeiterfassung persistente Objekte verwaltet. Diese müssen erzeugt, geändert, gelöscht und angezeigt
werden. Dafür wird meist ein Datagrid verwendet. In Kapitel 5.4.4 wird an einem
Beispiel die Verwendung eines Datagrids beschrieben.
Ein Beispiel für die Entwicklung eines User Controls, was in der Zeiterfassung
benötigt wird, wird in Kapitel 5.4.5 beschrieben.
5.4.2
Struktur der GUI
Die Benutzeroberfläche besteht, wie in Abbildung 27 dargestellt ist, aus drei PlaceHoldern:
51
Abbildung 27: Seitenaufbau der Default-Webform
PhHead In den PlaceHolder PhHead wird eine konstante UserControl eingefügt,
die ein Firmenlogo und ein Logo der Applikation enthält.
PhNavigation In den PlaceHolder PhNavigation wird das UserControl Navigator/Main hineingeladen, das abhängig von den Benutzerrechten des aktuellen
Benutzers alle ihm verfügbaren Menüpunkte anzeigt. Auf die Benutzerrechte
wird in Kapitel 5.6 genauer eingegangen.
PhContent Der interessante Teil ist der PlaceHolder PhContent, der abhängig vom
Benutzerzustand eine entsprechende UserControl enthält. Diese kann weitere
PlaceHolder enthalten, die wiederum UserControls besitzen.
Eine sprachliche Beschreibung, in welchem Zustand sich der Benutzer in der Zeiterfassung zum aktuellen Zeitpunkt befindet, wird in LHead dargestellt. Die Steuerung der Benutzeroberflächen wird in Kapitel 5.5.1 beschrieben. Fehlermeldungen
und Benutzerhinweise werden in dem Label LInfo dargestellt.
Abbildung 28 zeigt die entsprechende Klassenstruktur zu der grafischen Benutzeroberfläche aus Abbildung 27.
Die Webform Default wird dabei in zwei Klassen modelliert, welche die Stereotypen (siehe auch [UML]) ClientPage und ServerPage besitzen. Diese beiden Klassen
zeigen den serverseitigen (ServerPage) und den clientseitigen (ClientPage) Aspekt
dieser Webform (vgl. [Con 99]).
Der serverseitige Aspekt besitzt beispielsweise einen direkten Zugriff auf die Businesslogik und damit auch die Datenbank, während die clientseitige Webform diese
nur über die serverseitige Webform erreichen kann. Beim Ausführen von Funktionalitäten muss außerdem unterschieden werden, ob diese auf dem Client (beispielsweise
durch Javascript) oder auf dem Server ausgeführt wird.
52
Abbildung 28: Die Webform Default und die Codebehind-Klasse PageFrontdoor
Das HTML-Formular in der Webform wird durch eine Aggregationsbeziehung
modelliert, d. h., die Webform aus clientseitiger Sicht enthält ein Formular, was
wiederum Attribute (die HTML- bzw. Webform-Elemente) besitzt. Die Verbindung
zwischen der serverseitigen und der clientseitigen Webform wird durch eine Assoziation mit dem Stereotypen Build modelliert. Diese modelliert das Erzeugen einer
clientseitigen Webform bzw. Webseite.
5.4.3
Problem bei Web-Applikationen
Eine Eigenschaft, die eine Web-Applikation im Vergleich zu anderen Applikationen
besitzt, ist die, dass der Client ein Web-Browser ist. Während in einer Nicht-WebApplikation die Möglichkeiten des Benutzers ziemlich genau eingegrenzt werden,
müssen bei einer Web-Applikation die Möglichkeiten des Browsers mit berücksichtigt werden. In Abbildung 29 sind einige Beispiele hierfür darstellt.
Aus diesem Grund wurde eine Lösung mit nur einer Frame entwickelt und die
Applikation besitzt lediglich einen Einstiegspunkt. Den ”Zurück”-Button vollständig
abzufangen ist nicht möglich. In vielen Fällen führt dieser aber in ASP.NET zu
einem Fehler, auf den entsprechend reagiert werden kann (siehe Kapitel 5.5.1). Die
Benutzermöglichkeiten werden auf Buttons und Javascript-Events beschränkt, damit
besteht (fast) keine Möglichkeit, mehrere unkontrollierte Instanzen des Browsers zu
erzeugen. Für jede neue Instanz wird eine eigene Session erzeugt, damit sind zwei
Instanzen auch zwei unabhängige Benutzer in der Web-Applikation.
53
• Die Webseiten können direkt aufgerufen werden, damit sind beliebige Einstiegspunkte in die Applikation möglich.
• Durch den ”Zurück”-Button besteht immer die Möglichkeit, auf vorherige Seiten zuzugreifen. Bei einer Nicht-Web-Applikation ist dies nur möglich, wenn
diese Funktionalität explizit implementiert wurde. Wenn der Browser diese
Seite dann auch noch aus dem Cache holt, besteht ein weiteres Problem. Eine
Seite, die vielleicht durch einen Lock gesperrt und wieder freigegeben wurde,
ist für den Client sichtbar, ohne dass der Lock erneut gesetzt wurde.
• Durch Erzeugen einer neuen Browser-Instanz können mehrere Instanzen der
Applikation parallel laufen. Der Server kann nicht unterscheiden, wann eine
weitere Instanz gebildet und von welcher eine Anfrage gestellt wurde.
• Bei der Verwendung von Frames werden mehrere unabhängige Instanzen des
Browsers erzeugt, was zu weiteren Problemen führen kann. Die Zustände der
Frames müssen u. U. zueinander bestimmte Bedingungen erfüllen, die nur
schwer einzuhalten sind. Ein weiteres Problem ist, dass nur ein einziges Frame
abstürzen kann und somit die Applikation unvorhersehbare Zustände erreichen
kann.
Abbildung 29: Eigenschaften einer Web-Applikation
5.4.4
Verwendung eines Datagrids
Ein Beispiel für ein ServerControl ist das Datagrid. Mit dem Datagrid können, wie
in Abbildung 30 dargestellt ist, Datenmengen in Tabellenform angezeigt werden.
Aus der Sicht des Servers ist ein Datagrid ein Objekt. Dieses besitzt verschiedene
Properties, Methoden und Events. Die Spalten können dabei mithilfe von Flags einund ausgeblendet werden.
Abbildung 30: Beispielanwendung für ein Datagrid
54
Die Spalten können in einem Datagrid mit verschiedenen Spaltentypen definiert
werden, die im Folgenden, an dem Beispiel von Abbildung 30, beschrieben werden.
Wie bereits in Kapitel 5.3.3 beschrieben wurde, besitzt jedes persistente Objekt
eine Identität, die in der ersten Spalte des Datagrids gesetzt und für die Ansicht
ausgeblendet wird. Über diese Spalte können die Objekte bzw. Zeilen identifiziert
werden. Die einzelnen Zeilen des Datagrids besitzen zwar eine eigene Nummerierung,
da diese aber automatisch vergeben wird und nicht geändert werden kann, musste
auf eine versteckte Spalte zurückgegriffen werden. Diese Spalten (BoundColumn)
werden auch für die Darstellung der übrigen Daten (in diesem Fall nur Status) verwendet.
Eine weitere Spaltenart ist die Buttonspalte (ButtonColumn). Das Datagrid bietet für solche Spalten ein Event an. Über Delegation kann diesem Event eine Methode
übergeben werden. Beim Werfen dieses Events (also beim Betätigen des Buttons)
kann durch die mitgegebene Methode entsprechend reagiert werden. In diesem Fall
wird eine neue Benutzeroberfläche für die Arbeitszeitverteilung auf Projekte des
ausgewählten Mitarbeiters angezeigt.
Die Eingabefelder (Arbeitszeit) stellten im Datagrid eine Schwierigkeit dar. Das
Datagrid stellt dafür keine eigene Spaltenart zur Verfügung. In diesem Fall wurde
eine Template-Spalte (TemplateColumns) definiert, in der das entsprechende Eingabefeld einfügt wurde. Damit ist es Bestandteil einer Zeile (Item) und kann über die
Methode FindControl des Items ermittelt werden.
Aus der Sicht des Clients ist ein Datagrid eine HTML-Tabelle, welche Daten,
Eingabefelder und Buttons enthält. Die Zusammengehörigkeit dieser Daten existiert
im HTML nicht. Wird beispielsweise ein Button betätigt, so wird eine Anfrage an
den Server gesendet und die HTML-Elemente werden wieder zu einem DatagridObjekt ”zusammengesetzt”.
5.4.5
Entwurf eines User Controls
ASP.NET stellt zwar ein Kalender Server Control zur Verfügung, mit dem ein Datum
ausgewählt bzw. angezeigt werden kann, bietet aber keine Möglichkeit, ein Datumsfeld in einfacher und weniger Platz raubenden Form darzustellen, wie in Abbildung
31 zu sehen ist.
Abbildung 31: Beispiel für ein User Control
Abbildung 32 zeigt die dazugehörige Klasse, die von der Klasse UserControl abgeleitet werden muss und die OnInit-Methode überschreibt. In der OnInit-Methode
55
wird dem Load - bzw. PreRender -Event über Delegation eine entsprechende Methode übergeben.
Abbildung 32: Klasse DateControl
Das voreingestellte bzw. angezeigte Datum wird dabei in Attributen gespeichert
und kann über die entsprechenden Properties gelesen werden. Das Ändern des voreingestellten Datums geschieht durch die überladene Methode SetDefaultDate. Ein
Problem stellt hierbei der angezeigte Jahreszahlenraum dar. Ein Geburtsdatum besitzt beispielsweise einen anderen Jahreszahlenraum wie das Jahr eines Projektstarts. Die Methode SetYearLimit setzt diesen Jahreszahlenraum.
Abbildung 33: Sequenz Diagramm zum DateControl am Beispiel Mitarbeitereingabemaske
In Abbildung 33 ist eine beispielhafte Anwendung für ein UserControl dargestellt. Für jeden angelegten Mitarbeiter wird ein Datum der Aktivierung festgelegt.
56
Da ein Objekt vom Typ DateControl auch als Kopie auf dem Server gehalten wird,
muss das voreingestellte Datum nicht bei jeder Ausgabe neu geladen werden, d. h.,
eine wiederholte Anfrage (IsPostBack ) desselben UserControls muss das Datum des
Mitarbeiters nicht erneut ermitteln.
Wird die Methode SetYearLimit nicht aufgerufen, so wird ein voreingestellter
Jahreszahlenbereich von [aktuelles Jahr -5; aktuelles Jahr +5] definiert, bzw. wenn
ein voreingestelltes Datum mit einem Jahr gesetzt wird, wird der Jahreszahlenbereich entsprechend erweitert.
5.5
5.5.1
Zustandsmanagement
PageNavigator
Wie in Kapitel 4.4 beschrieben wurde, stellt das ASP.NET Page Framework verschiedenste Mechanismen zur Verfügung, um Zustandsinformationen zu verwalten.
Jeder Benutzer, der die Web-Applikation startet, d. h. die Web-Applikation im WebBrowser aufruft, erhält vom ASP.NET Page Framework eine eindeutige Session zugewiesen. Damit hat die Web-Applikation die Möglichkeit, die Anfragen der verschiedenen Benutzer zu unterscheiden. Wie in Abbildung 28 auf Seite 53 zu sehen
war, stellt die Klasse Page eine Property mit dem Namen Session zur Verfügung.
Zu jeder Session wird ein Session Objekt erzeugt, an das über einen Indexer verschiedene Werte gebunden werden können.
Die verschiedenen Zustände der Benutzer in der Web-Applikation müssen in
irgendeiner Form unterschieden werden. Wie bereits erwähnt wurde, stellt ASP.NET
dafür keine Technik zur Verfügung.
Die Klasse PageNavigator, wie in Abbildung 34 dargestellt ist, ist für die Steuerung der Benutzerzustände zuständig. Eine Instanz der Klasse PageNavigator, oder
einer spezifischen Form davon, wird an das Session Objekt gebunden bzw. wird
diesem zugewiesen. Abhängig davon, in welchem Funktionsblock sich der Benutzer
aktuell befindet, wird jeweilig eine der in Abbildung 34 dargestellten spezifischen
PageNavigator Objekte erzeugt.
Jeder Funktionsblock verwaltet in irgendeiner Form persistente Objekte, die eine
Identität besitzen. Das Property ID in der Klasse PageNavigator hat dabei folgende
Bedeutung:
ID = -1 Es wurde kein persistentes Objekt ausgewählt, d. h., die Liste oder Tabelle
der persistenten Objekte wird angezeigt.
ID = 0 Der Benutzer befindet sich in einem Zustand, in dem er eine Eingabemaske
sieht, um ein neues Objekt dieses Typs anzulegen.
57
Abbildung 34: Beispielklasse des PageNavigators zur Steuerung der Benutzeroberfläche
ID > 0 Der Benutzer hat ein bestimmtes Objekt mit der Identität ID ausgewählt,
um etwas damit zu tun. Im einfachsten Fall möchte er es bearbeiten und sieht
eine Eingabemaske mit den änderbaren Daten.
Abbildung 35: Abhängig vom PageNavigator werden die jeweiligen Templates geladen
Wie in Abbildung 35 an dem Beispiel Administration zu sehen ist, wird abhängig
von dem Property ID eines der beiden Templates in das Haupt Template (PhAdminContent) der Administration geladen. Der Zustand ID > 0 ist in diesem Fall
nicht möglich, da diese Entitäten nicht geändert werden dürfen.
Eine weitere Gemeinsamkeit aller Funktionsblöcke ist die, dass jeder Funktionsblock ein Haupt Template besitzt. Der Name dieses Templates wird durch das Property Content ausgelesen und im Konstruktor des jeweiligen PageNavigators gesetzt.
58
Abhängig von den jeweiligen Funktionsblöcken und Zuständen darin werden weitere Properties definiert, welche den Aufbau der Oberfläche beschreiben. Ein Beispiel
dafür ist das Property AdminKind in AdminNavigator. AdminNavigator beschreibt
den Aufbau der Administrationsoberfläche. Dort können Kostenstellen, Projekttypen, Projektgruppen und Aufgabenkataloge verwaltet werden. Das Property AdminKind beschreibt, in welchem dieser vier Zustände sich der Benutzer aktuell befindet,
oder ist NULL, wenn die Begrüßungsseite der Administration angezeigt wird.
Abbildung 36: Beispiel für Zustandsänderung mit PageNavigator
Das Beispiel aus Abbildung 36 soll diesen Mechanismus erklären (vgl. dazu auch
Abbildung 34):
Der Benutzer betätigt den Navigationsbutton ”Administration” (Event ButtonAdminClick in Abbildung 36) und gelangt in den Zustand ShowAdminMenu. In
diesem Zustand steht dem Benutzer ein Untermenü mit den oben genannten Administrationspunkten zur Verfügung (vgl. in Abbildung 34 mit Enumeration AdminKind ).
Betätigt der Benutzer den Untermenüpunkt Kostenstelle (Event ButtonCostCenterClick in Abbildung 36), so wird AdminKind auf COSTCENTER gesetzt. In
diesem Zustand sieht der Benutzer einen Button mit der Aufschrift ”Eine neue Kostenstelle anlegen”, welcher beim Betätigen das Event ButtonNewCostCenterClick
wirft und ID auf 0 setzt.
Da mit jeder Serveranfrage auch die Session Informationen mitgeschickt werden, ”kennt” die Web-Applikation ebenfalls das PageNavigator -Objekt und kann,
abhängig vom Zustand des PageNavigator -Objekts, die entsprechenden UserControls ”zusammensetzen”.
59
5.5.2
Start einer Session
Eine weitere Besonderheit bei einer Web-Applikation ist die Tatsache, dass diese Applikation nur läuft, wenn entsprechende Anfragen an den Server gesendet werden.
Eine Web-Applikation ist demnach keine Applikation, die als dauerhafter Prozess
läuft und somit z. B. nach definierten Zeiträumen bestimmte Aktualisierung vornehmen kann.
Abbildung 37: Sequenz Diagramm für das Starten einer Session
Ein Problem stellen dabei die Kalenderwochen in der Datenbank dar. Die Verteilung der Arbeitszeit auf die Projekte wird wochenweise durchgeführt. Für jede
abgelaufenen Woche muss in der Datenbank eine neue Woche angelegt werden. Es
besteht zwar die Möglichkeit, diese erst zu aktualisieren, wenn sie entsprechend benötigt wird, da dies aber an verschiedensten Stelle nötig ist, wurde die Aktualisierung,
wie in Abbildung 37 zu sehen ist, beim Starten einer Session durchgeführt (in der
Klasse Global wird das Event Session Start geworfen).
Die Authentifizierung des Benutzers bzw. Mitarbeiters (SelectEmployeeByAccount) wird im folgenden Kapitel beschrieben.
5.6
Benutzerrechte
In diesem Kapitel geht es darum, die Mitarbeiter bzw. die Benutzer in der Zeiterfassung zu authentifizieren. Authentifizierung ist die Überprüfung der Identität eines
Benutzers.
Die integrierte Windows-Authentifizierung (vgl. [GotDotNet]) von ASP.NET bietet die Möglichkeit, auf die Daten der NT-Konten der Benutzer zuzugreifen. Da sich
jeder Mitarbeiter in der Firma FP an seinem Arbeitsplatzrechner authentifizieren
muss, bot sich diese Technik an. Der Browser kommuniziert dabei mit dem Server in
einer verschlüsselten Form, wobei das Passwort selber nicht übertragen wird (siehe
[Loh 03, Kap. 13]).
60
Wird die Zeiterfassung gestartet, so werden die Authentifizierungsdaten an den
Server gesendet und sofern dieser Benutzer berechtigt ist, bekommt er den Zugang
zum System.
Zunächst wurde in der Analyse von einer eigenständigen Authentifizierung ausgegangen, d. h., zu jedem Mitarbeiter wird ein Passwort angelegt. Dafür muss eine entsprechende Authentifizierungsmaske entwickelt werden. Dabei mussten verschiedene
Probleme berücksichtigt werden: Wer darf das Passwort sehen? Wird das Passwort
verschlüsselt und wenn ja mit welchem Verfahren? Was passiert, wenn ein Benutzer
sein Passwort vergessen hat? usw.
Die bis dahin beschriebenen Anforderungen mussten geändert werden. Wie sich
bei weiteren Befragungen herausgestellt hat, besitzt der Benutzer nicht nur ein NTKonto, sondern beliebig viele, d. h., für jeden Benutzer wird eine Menge von Konten
bzw. Accounts angelegt (vgl. mit Abbildung 8 auf Seite 28 und siehe auch EmployeeAccount in 55 auf Seite 85).
Diese Lösung funktioniert nur unter einigen Voraussetzungen. Da der Benutzer
über das NT-Konto authentifiziert wird, muss ein entsprechendes auch in der Domäne existieren. Ein Problem bei diesem Mechanismus ist die Abhängigkeit zu einem
Windowsserver. Außerdem muss der Browser ein Internet Explorer sein. Da diese
Bedingungen in der Zeiterfassung aber erfüllt waren, stellt dieser Mechanismus eine
gute Lösung dar.
Im Namespace System.Security.Principal stellt ASP.NET eine Klasse WindowsIdentity zur Verfügung, die einen Windowsbenutzer repräsentiert. Über diese Klasse
wird der Benutzername des NT-Kontos (Account) des Benutzers ermittelt.
Beim Event Session Start in der Klasse Global wird zu dem Account ein entsprechender Benutzer ermittelt (siehe SelectEmployeeByAccount in 5.3.5). Die Benutzerechte in der Zeiterfassung sind dabei verschieden von denen in der Domäne
und werden an das Session Objekt gebunden.
Damit stehen die Benutzerrechte überall in der Zeiterfassung zur Verfügung und
können entsprechend verwendet werden, um z. B. bestimmte Spalten im Datagrid
auszublenden oder in der Navigation nur bestimmte Buttons anzuzeigen.
5.7
5.7.1
Zusammenfassung
Gesamtstruktur
Die zuvor vorgestellten Konzepte werden im Folgenden anhand des Beispiels Mitarbeiterverwaltung von Abbildung 38 zusammengefasst.
61
Abbildung 38: Zusammenfassende Darstellung am Beispiel Mitarbeiterverwaltung
Der Einstiegspunkt in die Zeiterfassung ist die Webform Default mit ihrer dazugehörigen CodeBehind Klasse PageFrontdoor. Die Verbindung zwischen der Klasse
PageFrontdoor und dem Template Main stellt das Laden des Templates in den PlaceHolder PhContent dar (vgl. Kapitel 5.4.2).
Gemäß Kapitel 5.4 beschreibt der Namespace WebControl.Employee in Abbildung 38 in der Komponente ProjectManagement.Core einen beispielhaften Aufbau
für die zwei Templates Main und EmployeeList. Die Templates werden von einer
spezifischen Klasse von UserControlBasic abgeleitet. In diesem Fall ist dies EmployeeUserControl. In diesen Klassen werden weitere Methoden definiert, die in mehreren
Templates des Funktionsblocks benötigt werden. Die Klasse UserControlBasic, wel62
che einen Funktionsblock repräsentiert, wird von UserControl abgeleitet und stellt
einige Properties zur Verfügung. Das Setzen des Properties Info setzt beispielsweise
einen Benutzerhinweis auf der Webform Default (siehe LInfo in Kapitel 5.4.2). Die
Klasse UserControlBasic besitzt außerdem ein Property, welches den aktuellen Benutzer mit seinen Benutzerrechten repräsentiert (siehe Kapitel 5.6). Die Schnittstelle
zur Businesslogik bildet das Property Controller.
Das Property PageNavigator bzw. in diesem Fall das spezifische Property EmployeeNavigator repräsentiert das PageNavigator Objekt, was an die Session gebunden wird. Dieses beschreibt die Zusammensetzung der Oberfläche, d. h. wie die
Templates miteinander in Abhängigkeit stehen (siehe Kapitel 5.5).
Die Klasse EmployeeManager ist eine beispielhafte Managerklasse, wie in 5.2
und 5.3 beschrieben wurde.
5.7.2
Beispielhafter Ablauf
Abbildung 39: Sequenz Diagramm bei einer Serveranfrage ohne Event
Abbildung 40: Sequenz Diagramm bei einer Serveranfrage durch ein Event
63
In Abbildung 39 und 40 sind zwei beispielhafte Abläufe einmal mit und einmal
ohne Event dargestellt. Beim Aufrufen eines Oberflächenzustandes durch ein Event
(beispielsweise durch Betätigen eines Buttson) wird, wie in Abbildung 40 dargestellt,
für jedes Template das Event Load geworfen bzw. die Methode Page Load aufgerufen. An das Event ”Betätigen des Buttons neuen Mitarbeiter anlegen” wird eine
Methode mit dem Namen BtShowInsertMask Click gebunden, die in diesem Fall
aufgerufen wird. Diese ändert den Zustand des PageNavigator Objekts (vgl. Abbildung 36 auf Seite 59) und ruft die Reload-Methode auf, die in UserControlBasic
definiert wurde. Diese führt zu einer neue Anfrage am Server (mit dem geänderten
PageNavigator ).
Die neue Anfrage an den Server (siehe Abbildung 40) wirft dann ebenfalls das
Event Load, was in den jeweiligen Templates die Methoden Page Load aufruft. Das
anschließende Event PreRender (mit der Methode Page PreRender ) setzt die Inhalte
der einzelnen Templates. An dem Beispiel von Abbildung 38 ist dies die Darstellung
aller Mitarbeiter, die durch LoadArrayList aus der Businesslogik geholt werden.
5.7.3
Schwierigkeiten beim Entwurf
Die fehlende Vererbung im Persistenz Framework erzwang bereits beim Entwurf
flache Strukturen, d. h. Strukturen ohne Vererbung. Beispielsweise ist Wiederverwendbarkeit in den konkreten Managerklassen nicht möglich, da diese von ihren spezifischen abstrakten Managerklassen abgeleitet werden müssen (siehe Kapitel 5.3.1).
Das nächste Problem stellen die verschiedenen Anfragemöglichkeiten dar. Für
jede Anfrage, beispielsweise Projekte mit Fachgruppen, die bereits geschlossen sind,
oder Projekte ohne Fachgruppen eines bestimmten Monats, muss eine abstrakte Methode in der Komponente ProjectManagement.Core definiert und in den konkreten
Managern implementiert werden.
Problematisch an dieser Struktur waren auch die Änderungen. Eine Änderung
führt zu einer Änderung in den entsprechenden spezifischen und konkreten persistenten Objekten und entsprechend auch in den dazugehörigen Managern.
Der Vorteil an dieser Variante ist nicht nur die logische, sondern auch die physikalische Trennung zwischen Implementierung und Entwurf. Wie bereits in Kapitel
5.1 beschrieben wurde, soll der Entwurf die Analyse erweitern bzw. verfeinern, was
durch Definition der abstrakten Methoden in den Klassen des Persistenz-Frameworks
durchgeführt wird. Vererbung kann dabei nur auf Spezifikationsebene durchgeführt
werden, wie in Abbildung 26 in Kapitel 5.3.5 an der Klasse SimpleObject zu sehen ist.
Kostenstellen (CostCenter ), Projekttypen (ProjectType), Projektgruppen (ProjectGroup) und Aufgabenkataloge (Activity) haben die gleichen Properties: ID, Name
und Beschreibung. Wie bereits erwähnt wurde, ist diese Struktur in den konkreten
64
Komponenten nicht mehr möglich.
Die Trennung nach dem Model-View-Controller Pattern ist ebenfalls gegeben.
Das Persistenz-Framework besitzt dabei die Rolle des Modells, die Webform und die
Templates bilden die View und die Codebehind Klassen mit ihrem PageNavigator
(siehe Kapitel 5.5.1) nehmen die Rolle des Controllers ein.
Die Entwicklung in einem Framework ist nicht ganz einfach, da nur an den vordefinierten Schnittstellen angesetzt werden kann. Beispielsweise habe ich erst sehr
spät herausbekommen, dass es ein PreRender Event gibt, wobei man sich vorstellen
kann, wie eine Implementierung ohne dieses Event ausgesehen hat, da nach dem
Werfen der Benutzer Events keine Methode mehr zur Verfügung stand.
Ein weiteres Problem für einen Web-Programmierer ist die Vorstellung, dass
HTML-Elemente Objekte mit Events und Methoden sind. Die etwas andere Form
der Webseitengestaltung hat aber auch einige Nachteile. Über das Visual Studio
lassen sich zwar die Oberflächen einfach zusammenklicken, aber wenn man besondere Wünsche hat (siehe Kapitel 5.4.4), wird man gezwungen Manipulationen in den
automatisch erzeugten Webforms bzw. Templates vorzunehmen, die nicht gerade
einfach zu lesen sind.
Die Entwicklung und Verwendung des PageNavigators (siehe Kapitel 5.5.1) war
prinzipiell eine gute Idee, wobei sich die Controller-Funktion des Model-View- Controller Patterns für jede Oberfläche auf drei Klassen verteilt hat: die CodeBehind
Klasse, die spezifische UserControlBasic Klasse und den spezifischen PageNavigator.
5.7.4
Nebenläufigkeit
Ein Problem bei der Entwicklung einer Web-Applikation ist die Nebenläufigkeit.
Wie noch im Kapitel 6.3.3 gezeigt wird, stellten nebenläufig arbeitende Aktionen
ein Problem dar. In Kapitel 6.3.3 wird die Nebenläufigkeitsproblematik zwischen
Businesslogik und Datenbank beschrieben. Ein anderes Problem ist die Nebenläufigkeit zwischen Client und Businesslogik. Eine Web-Applikation besitzt im Vergleich zu einer Nicht-Web-Applikation (siehe Kapitel 5.4.3) einige Besonderheiten.
Beispielsweise kann der Zustand der grafischen Benutzeroberfläche eines Benutzers
nie wirklich eindeutig bestimmt werden. Aus diesem Grund muss jedem Benutzer
Event bzw. Serveranfrage sichergestellt werden, dass die Operationen, die ausgeführt
werden sollen, im aktuellen Zustand noch zulässig sind.
5.7.5
Übergang zur Implementierung
Die in den spezifischen Managerklassen und den persistenten Objekten definierten
abstrakten Methoden müssen für die spezifische Komponente mit Funktionalität
65
gefüllt werden, d. h., von jeder dieser Klassen muss eine abgeleitete Klasse entwickelt werden, welche die abstrakten Methoden implementiert. Instanzen dieser
Klasse müssen an eine von Controller abgeleitete Klasse gebunden werden.
66
6
Implementierung mit relationaler Datenbank
6.1
Einleitung
Die relationale Datenbank basiert auf dem Relationenmodell, welches von E. F.
Codd 1970 [Cod 70] vorgestellt wurde. Das grundlegende Konzept der relationalen
Datenbank ist die Tabelle13 . Eine Tabelle besitzt eine definierte Anzahl von Attributen (Spalten) und eine beliebige Menge von Tupeln. Die Tupel repräsentieren die
Datensätze. Über so genannte Schlüsselverbindungen, wie in Kapitel 6.2 noch gezeigt wird, werden Beziehungen zwischen den Tabellen realisiert.
Die Kommunikation zwischen der Anwendung14 und der Datenbank erfolgt über
die standardisierte Stuctured Query Language (SQL). Eine relationale Datenbank
ist immer ein von der Anwendung unabhängiges System. Die Probleme, die durch
diese Trennung entstehen, werden im weiteren Verlauf noch beschrieben. In Form
eines Strings (Query) werden Anweisungen oder Abfragen formuliert, die an die
Datenbank gesendet und dort entsprechend ausgeführt werden. SQL kann in drei
Teilsprachen unterteilt werden:
Die Datendefinitionssprache (DDL) enthält Befehle zum Anlegen, Ändern und
Löschen von Strukturen bzw. Tabellen. Die einzelnen Möglichkeiten und Probleme
werden in Kapitel 6.2 beschrieben.
In der Datenmanipulationssprache (DML) werden Befehle zum Erzeugen, Ändern und Löschen von Daten definiert. Die Funktionsweise der Datenmanipulation
und die Problematik, insbesondere bei nebenläufigen Manipulationen, werden in Kapitel 6.3 beschrieben.
Die dritte Teilsprache von SQL ist die Abfragesprache (QL), mit der die einzelnen Daten abgefragt werden. Diese wird in Kapitel 6.4 vorgestellt.
Redundanzvermeidung durch Normalisierung ist einer der entscheidenden Vorteile einer relationalen Datenbank. Durch mathematische Regeln, die auf der Arbeit
von [Cod 70] basieren, können Redundanzen vermieden bzw. gemindert werden. Dieses Thema wird in Kapitel 6.5 behandelt.
In Kapitel 6.6 wird anhand des Beispiels der ODBC-Schnittstelle beschrieben,
wie aus der Sicht der Anwendung mit der Datenbank kommuniziert wird.
Basierend auf den Grundlagen von Kapitel 6.2-6.6 wird in Kapitel 6.7 das kon13
In der Relationstheorie spricht man von Relationen und in der Datenbank von Tabellen. Prinzipiell sind Tabellen Relationen, die in einer (relationalen) Datenbank verwendet werden.
14
Die Anwendung ist in diesem Fall die Applikation ”Zeiterfassung”.
67
krete Datenmodell der Applikation Zeiterfassung vorgestellt.
In Kapitel 5.3 wurde bereits das entwickelte Framework vorgestellt, was eine
Trennung von Entwurf und Implementierung ermöglicht. Die Beispiele im Folgenden beziehen sich auf dabei vorgestellten Managerklassen aus Kapitel 5.3.
Bei der Entwicklung einer relationalen Datenbank ergeben sich etliche Schwierigkeiten und Schwächen, wie in den folgenden Kapiteln noch gezeigt wird. In Kapitel
6.8 werden diese zusammengefasst und mit einer Motivation zur Objektorientierung
in Datenbanken abgeschlossen.
Die Beschreibungen basieren auf dem SQL-99 Standard, allerdings ohne die objektrelationalen Erweiterungen. Da SQL-99 abwärts kompatibel zu SQL-92 ist, sind
darin auch alle Möglichkeiten von SQL-92 enthalten. Dabei werden nur die Punkte
behandelt, die für die Realisierung und den Vergleich relevant sind. Weitere Konzepte, wie beispielsweise Schemata, mit denen logisch zusammengehörige Tabellen
weiter strukturiert werden können, werden nicht behandelt.
6.2
6.2.1
Datendefinition
Datentypen und Domänen
Für jedes Attribut wird ein Wertebereich definiert. Dieser Wertebereich wird als
Domäne bezeichnet. Neben vordefinierten Domänen besteht die Möglichkeit, eigene
Domänen zu definieren. Diese basieren auf vordefinierten Domänen und können diese einschränken. Ein Beispiel für eine Domäne ist eine Prozentdefinition, die durch
den Query ”CREATE DOMAIN Percent INTEGER CHECK(BETWEEN 0 AND
100)” definiert werden kann.
Benutzerdefinierte Domänen sind nicht streng typisiert, da sie keine Typen im
eigentlichen Sinne sind, d. h., ein Vergleich von Percent und einem Attribut vom
Typ Integer mit dem Wert 101 wäre zulässig (vgl. [Tür 03, S. 26]).
Domänen sind atomar, d. h., Strukturen in Attributen sind nicht möglich. Die
Konsequenzen daraus, die sich für die Datenmodellierung ergeben, werden im weiteren Verlauf noch beschrieben.
6.2.2
Primärschlüssel
Zur Identifizierung eines Tupels wird in einer Tabelle ein Primärschlüssel definiert.
Dieser kann entweder aus einem einzelnen oder aus einer Gruppe von Attributen
(zusammengesetzter Schlüssel) bestehen. Der Primärschlüssel darf nicht NULL sein
und muss für jedes Tupel eindeutig vorliegen.
68
Die Betrachtung eines Primärschlüssels als Identität, wie es in vielen Fällen getan wird, hat einen entscheidenden Nachteil. Wenn der Wert des Primärschlüssels
geändert wird, so bedeutet das, dass sich die Identität eines Tupels ändert, was aber
falsch ist.
Ein konkretes Beispiel ist das Projekt, wie in Kapitel 6.7 auf Seite 83 noch gezeigt wird. Ein Projekt wird durch eine Projektnummer (ProjectID) identifiziert,
welche gleichzeitig der Primärschlüssel ist. Eine Änderung der Projektnummer, beispielsweise weil eine Projektnummer falsch eingegeben wurde, bedeutet aber keine
Änderung der Identität des Projekts (vgl. auch [Saa 03, S. 47 f.]).
Aus diesem Grund wurden - bis auf das Projekt - für alle Entitäten unveränderliche Schlüssel definiert. Der Datentyp ”serial” in der Abbildung 55 auf Seite 85
erzeugt automatisch eine fortlaufende eindeutige Zahl. Die Anwendung, also die Zeiterfassung, braucht sich in diesem Fall nicht mehr um die Eindeutigkeit zu kümmern.
6.2.3
Fremdschlüsselverbindungen und referentielle Integrität
Um zwei Tabellen miteinander in Beziehung zu setzen werden Fremdschlüssel definiert. Ein Fremdschlüssel kann, genau wie ein Primärschlüssel, für ein einzelnes
Attribut oder eine Gruppe von Attributen definiert werden. Zu jedem Fremdschlüssel in einer Tabelle gibt es einen dazugehörenden Primärschlüssel in einer anderen
Tabelle.
Dabei müssen Fremdschlüsselverbindungen die referentielle Integrität gewährleisten. Referentielle Integrität bedeutet, dass zu jedem Fremdschlüsselwert in einer
Tabelle ein entsprechender Primärschlüssel existiert, der den gleichen Wert besitzt,
oder der Fremdschlüssel ist NULL, d. h., ein Fremdschlüssel muss immer auf einen
existierenden Primärschlüssel verweisen (vgl. [Vor 99], S. 89).
6.2.4
Integritätsbedingungen
Durch Änderungen an den Daten können Schlüsselbedingungen verletzt werden und
die referentielle Integrität ist dann nicht mehr gegeben. Wie in [Tür 03, S. 20] beschrieben, tritt dies ein, wenn einer der folgenden Punkte erfüllt ist:
• Einfügen einer Zeile in die referenzierende Tabelle.
• Ändern des Fremdschlüsselwertes einer Zeile in der referenzierenden Tabelle.
• Löschen einer Zeile aus der referenzierten Tabelle (oder Löschen einer referenzierten Tabelle).
• Ändern des korrespondierenden Schlüsselwertes einer Zeile in der referenzierten
Tabelle.
69
Zu Sicherung der referenziellen Integrität muss einer Fremdschlüsselverbindung
eine Eigenschaft (siehe Abbildung 41) mitgegeben werden, die beschreibt, wie eine
Verletzung der referenziellen Integrität behandelt wird.
NO ACTION: Wenn eine Fremdschlüsselbedingung beim Ändern oder Löschen
einer Zeile verletzt wird, wird diese Anfrage mit einem Fehler zurückgewiesen.
Allerdings kann die Integritätsverletzung mit einem Trigger behoben werden,
wodurch kein Fehler auftritt.
CASCADE (C): Die Änderung oder Löschung der Zeile wird kaskadiert. Wird
eine Zeile gelöscht bzw. geändert, so werden alle Zeilen, die auf diese Zeile
referenziert haben, mit gelöscht oder geändert.
SET NULL (SN) und SET DEFAULT (SD): Wird ein Primärschlüssel einer
Zeile geändert oder eine Zeile gelöscht, so werden die Fremdschlüssel, die auf
diese Zeile referenzierten, auf NULL bzw. den eingestellten Defaultwert gesetzt.
RESTRIKT (R): Restrikt weist eine Anfrage, genau wie No Action, zurück, wenn
eine Integritätsverletzung vorliegt. Ein Beheben der Integritätsverletzung mit
einem Trigger ist allerdings nicht möglich.
Abbildung 41: Referenzielle Aktionen nach [Tür 03, S. 21]
6.2.5
Trigger
Fremdschlüsselverbindungen können nur die Integrität zwischen zwei Tabellen, d.
h. die referentielle Integrität gewährleisten. Für komplexere Integritätsprüfungen
werden Trigger definiert. Ein Trigger führt, ähnlich zu einem Event, beim Eintreten
eines Ereignisses eine Folge von Anweisungen aus. Die möglichen Ereignisse nach
dem SQL-99 Standard, wie in [Tür 03, S. 37] beschrieben, sind das Einfügen, Ändern
oder Löschen von Tupel.
6.2.6
Benutzerdefinierte Routinen
Durch die Definition von benutzerdefinierten Routinen (stored procedures) besteht
die Möglichkeit, einfache Funktionalitäten in einer relationalen Datenbank auszuführen. Diese können, durch die Verwendung von atomar definierten Funktionsblöcken,
Definition von Variablen, bedingten Schleifen oder bedingten Anweisungen, zusätzliche Integrationsprüfungen oder analog zu den Sichten komplexe Abfragen realisieren.
Dabei ähnelt eine benutzerdefinierte Routine sehr einem Pascalprogramm, in welchem zusätzlich SQL-Statements enthalten sind.
70
So wie in [Tür 03, S. 32] beschrieben wird, sind nicht alle SQL-Statements zulässig. Beispiele für nicht zulässige SQL-Statements sind Transaktionsanweisungen, Anweisungen zur Steuerung der Datenbankverbindung und Transaktionsanweisungen.
Bei den benutzerdefinierten Routinen wird zwischen Prozeduren und Funktionen
unterschieden. Funktionen haben im Gegensatz zu Prozeduren einen Rückgabewert
und können auch in Queries verwendet werden, um z. B. Bedingungen zu definieren. Funktionen können außerdem überladen (overloading) werden (vgl. dazu auch
[Tür 03, S. 28-37]).
Die Funktionen und Prozeduren in Klassen zu organisieren und damit Vererbung
und dynamisches Binden zu ermöglichen, besteht nicht.
6.2.7
Sichten (Views)
Eine Sicht, auch als virtuelle Tabelle bezeichnet, repräsentiert eine SQL-Anfrage und
kann wie eine Tabelle verwendet werden. Änderungen in den Tupeln einer Sicht sind
zwar nach dem SQL-99 Standard unter sehr eingeschränkten Bedingungen möglich
(vgl. [Tür 03, S. 253 ff.]), da aber die mir zur Verfügung stehende Informix Datenbank Änderungen auf Sichten nicht unterstützt und die verwendeten Sichten die
Bedingungen überwiegend nicht erfüllt haben, wird im Folgenden davon ausgegangen, dass Änderungen an Sichten nicht möglich sind.
6.2.8
Schwächen der relationalen Datendefinition
Während in der Anwendung komplexe (objektorientierte) Datentypen verwendet
werden können, müssen diese in der relationalen Datenbank durch die fehlende Vererbung auf flache Strukturen abgebildet werden. Die Domänen (vgl. 6.2.1) können
zwar Wertebereiche definieren, sind aber keine echten Typen im eigentlichen Sinne.
Dadurch, dass sie nicht typsicher sind, können beliebige Daten unterschiedlicher Domänen miteinander verglichen und in Beziehung gesetzt werden.
In Kapitel 6.7.2 wird die Problematik bei der Modellierung des Modells von
Abbildung 8 auf Seite 28 in einer Struktur ohne Vererbung noch genauer beschrieben.
6.3
6.3.1
Datenmanipulation
Datenmanipulationsoperationen
Einfügen, Ändern und Löschen von Tupeln werden über die Insert-, Update- und
Delete-Statements durchgeführt. Diese Operationen sind auf einzelne Tabellen beschränkt, d. h., Operationen, die sich auf mehrere Tabellen verteilen, müssen in
einzelnen SQL-Statements angegeben werden. Die referentielle Integrität und eventuell durch Trigger zusätzlich definierte Integritätsbedingungen dürfen dabei nicht
71
verletzt werden. Damit ist gesichert, dass keine unzulässigen Zustände in der Datenbank vorkommen können.
6.3.2
(SQL-)Transaktionen
Eine Transaktion ist eine atomare Ausführungseinheit, die eine Folge von logisch zusammengehörigen Operationen umfasst und dem ACID-Prinzip, wie in Abbildung
42 dargestellt, entsprechen muss (vgl. [Saa 03, S. 275]).
Atomicity (Atomarität): Eine Transaktion stellt eine atomare Einheit dar, d. h.,
eine Transaktion wird entweder vollständig oder gar nicht ausgeführt.
Consistency (Konsistenz): Nach Abschluss einer Transaktion muss sich die Datenbank in einem konsistenten Zustand befinden.
Isolation: Parallel ablaufende Transaktionen dürfen sich gegenseitig nicht behindert, d. h., eine Transaktion muss immer so ablaufen, als wäre sie die einzige
auf der Datenbank. Änderungen an Daten in einer Transaktion dürfen in einer
anderen Transaktion nicht auftreten.
Durability (Dauerhaftigkeit): Beim Beenden einer Transaktion müssen alle Änderungen, welche durch die Transaktion verursacht wurden, dauerhaft (persistent) erhalten bleiben.
Abbildung 42: Die ACID-Eigenschaften, die eine Transaktion erfüllen sollte
In einer relationalen Datenbank werden dafür entsprechende Operationen zur
Verfügung gestellt, die eine Transaktion starten und erfolgreich (Commit) oder
durch Rückgängigmachen aller Operationen der Transaktion (Rollback ) beenden.
Erst wenn ein Commit durchgeführt wurde, sind alle Daten dauerhaft in der Datenbank gespeichert. Tritt während einer Transaktion ein Fehler auf, beispielsweise
weil eine Integritätsbedingung nicht erfüllt ist oder eine Query eine fehlerhafte Syntax besitzt, so verhält sich die Datenbank wie bei einem Rollback und erzeugt den
Zustand, der vor der Transaktion existierte. Dies funktioniert wunderbar unter der
Voraussetzung, dass keine weitere parallele Transaktion läuft. Durch das Bilden von
Transaktionen, in denen die Queries an die Datenbank gesendet werden, sind die
ACID-Eigenschaften Atomicity und Durability erfüllt.
6.3.3
Nebenläufigkeitsanomalien
Problematisch wird die Erfüllung der ACID-Eigenschaften Consistency und Isolation. Diese beziehen sich auf die Nebenläufigkeitsproblematik. Nebenläufige Leseund Schreiboperationen können, wie in Abbildung 43 dargestellt, zu inkonsistenten
72
Zuständen führen (vgl. [Vor 99, S. 143 f.]).
Dirty Read: Diese Problem tritt auf, wenn eine Transaktion Daten liest, die zuvor
von einer zweiten geändert wurden, und diese zweite Transaktion ein Rollback
ausführt. Das Rollback der zweiten Transaktion verwirft die Änderungen in der
Datenbank, aber die erste Transaktion verwendet noch die ”falschen” Daten.
Lost Update: Zwei Transaktionen lesen jeweils das gleiche Objekt und ändern dies
unabhängig. Die Änderungen der ersten Transaktionen werden dabei überschrieben.
Non-repeatable Read: Wenn eine Transaktion zweimal dasselbe Objekt liest und
es währenddessen geändert wurde, würde die zweite Leseoperation einen anderen Wert zurückliefern. Dies ist vor allem dann problematisch, wenn eine
wiederholte Anfrage abhängig von einem Ergebnis einer vorherigen Anfrage
ist.
Phantom Read: Das Problem Phantom Read tritt bei folgendem Ablauf ein: Eine
Transaktion holt sich Daten, die abhängig von einer Menge sind, die anschließend von einer zweiten Transaktion geändert wird. Die erste Transaktion verarbeitet diese Daten, welche die geforderten Bedingungen nicht mehr erfüllt.
Abbildung 43: Anomalien bei nebenläufigen Transaktionen nach [FO 04b]
In [FO 04b] wird noch eine weitere Anomalie mit dem Namen Reading of Inconsistent States beschrieben, die sich auf Verletzung von Bedingungen zwischen Daten
bezieht, da diese aber in der übrigen Literatur nicht zu finden war, wird sie hier
nicht weiter beschrieben.
Das folgende Beispiel soll das Problem Phantom Read verdeutlichen:
Transaktion 1 ermittelt alle Projekte, die keine Fachgruppen15 besitzen. Eine
zweite Transaktion fügt anschließend einem dieser Projekte eine erste Fachgruppe
hinzu. Die erste Transaktion enthält dabei in ihrer Projektmenge ein Projekt, welches
Fachgruppen besitzt, obwohl diese Transaktion davon ausgeht, dass sie die Liste aller
Projekte ohne Fachgruppen enthält.
6.3.4
Nebenläufigkeitskontrolle
Um die Kapitel 6.3.3 dargestellten Probleme zu beseitigen gibt es grundsätzlich zwei
Ansätze, die in diesem Kapitel beschrieben werden. Nebenläufigkeitskontrolle kann
15
In der realisierten Datenbank existiert zu jedem Projekt immer eine Default-Fachgruppe (vgl.
6.7). Das Problem bleibt aber das gleiche.
73
auf verschiedenen Ebenen durchgeführt werden. Im Folgenden wird nur von Dateneinheiten gesprochen, wobei es abhängig von der verwendeten Granularität ist, ob
eine Dateneinheit ein Wert, ein Tupel, eine Tabelle oder eine Datenbank ist.
Der erste Ansatz ist die pessimistische Nebenläufigkeitskontrolle. Diese basiert
auf einem Lock-Mechanismus. Eine bestimmte Dateneinheit kann von einer Transaktion entweder durch einen exklusive, write lock oder ein shared, read lock gesperrt
werden (vgl. [Vor 99, S. 150]. Dabei kann eine Dateneinheit entweder von beliebig
vielen Transaktionen mit einem shared, read lock belegt oder einer einzigen Transaktion mit einem exklusive, write lock gesperrt werden. Zugriffe auf gelockte Dateneinheiten werden von der Datenbank sofort zugewiesen, bzw. abhängig von der
Datenbank können auch Wartezeiten eingestellt werden. Wird der Lock während
dieser Wartezeit freigegeben, so kann die Transaktion, welche die gelockte Dateneinheit benötigt, ausgeführt werden (vgl. dazu auch [FO 04b]).
Der zweite Ansatz ist die optimistische Nebenläufigkeitskonrolle (vgl. [FO 04b]).
Die Prüfung, ob eine Lese- oder Schreiboperation unzulässig ist, wird beim Ausführen der jeweiligen Operation überprüft. Realisiert werden kann dieser Algorithmus
durch das Einführen von Zeitstempeln oder Versionierung der Dateneinheiten (vgl.
[FO 04b] und [Vor 99, S. 156 f.]).
Einen direkten Mechanismus gibt es beim relationalen Datenbankkonzept nicht.
Es besteht zwar die Möglichkeit, in einem Attribut eine Version oder einen Zeitstempel zu speichern und diesen Wert bei jeder Änderung zu aktualisieren. Das Problem,
was sich dabei stellt, ist, dass dieses spezielle Attribut ein Attribut wie jedes andere
auch ist und beliebig geändert werden kann. Viel schlimmer ist die Abfrage, ob ein
Wert noch aktuell ist. Die Versionsinformation muss beim Lesen eines Datensatzes
mit ausgelesen und beim Ändern entsprechend überprüft werden, ob dieser Wert
noch aktuell ist. Zumindest das Testen auf Aktualität und das Ändern sollten dann
in einer sperrenden Transaktion durchgeführt werden.
6.4
6.4.1
Datenabfragen (Select)
Select-Statement
Durch das Select-Statement werden, wie in Abbildung 44 dargestellt, Tupelmengen
aus Tabellen abgefragt.
Die From-Klausel enthält die Tabellen, aus denen die Daten abgefragt werden
sollen. In der Select-Klausel werden die Attribute angegeben, die zurückgeliefert
werden sollen. Die Where-Klausel gibt Bedingungen an, die auf die Ergebnismenge
zutreffen müssen. Abbildung 45 zeigt ein Beispiel mit zwei Tabellen. Um einen Verbund dieser beiden Tabellen zu erzeugen, werden die Schlüsselbedingungen in der
74
SELECT <Attribute>
FROM <Tabellen>
[WHERE <Bedingungen>]
[ORDER BY <Sortierreihenfolge>]
Abbildung 44: Einfache Darstellung des SQL-Select-Statements
Where-Klausel definiert, wie in Abbildung 46 dargestellt.
Abbildung 45: Verbund von zwei SQL-Tabellen
SELECT Employee.ID AS ID, AccountID, Firstname, Lastname, Account
FROM Employee, EmployeeAccount
WHERE Employee.ID=EmployeeAccount.ID
Abbildung 46: SQL-Select-Statement zu dem Beispielverbund von Abbildung 45
Des Weiteren können in der Select-Klausel berechnete Werte enthalten sein. Ein
Beispiel aus der Zeiterfassung ist die Select-Anfrage für Projekte. Dort wird u. a. ein
Attribut erzeugt, was die Summe aller Fachgruppen des jeweiligen Projekts enthält.
Abbildung 47 stellt eine ”einfache” Ad-hoc-Anfrage über alle Mitarbeiter, die in
einer ausgewählten Kalenderwoche an einem ausgewählten Projekt gearbeitet haben,
dar. Wie an diesem Beispiel zu sehen ist, können Anfragen nach einfachen Informationen ziemlich kompliziert werden und die Bedeutung einer Anfrage ist nicht sofort
erkennbar. Die definierten Fremdschlüsselverbindungen müssen dabei als Bedingungen mit angegeben werden. Solche Anfragen können bei sehr großen Datenmengen
durch die Verbund-Operation sehr rechenintensiv werden.
75
SELECT ... FROM Employee e, EmployeeContract ec,
EmployeeWeek ew, Week w, ProjectEmployee pe, Project p
WHERE e.EmployeeID = ec.EmployeeID
AND ec.ContractID = ew.ContractID
AND ew.EmployeeWeekID = w.WeekID
AND w.CalendarWeek = <ausgegewählte Kalenderwoche>
AND w.Year = <ausgewähltes Jahr>
AND ew.EmployeeWeekID = pe.EmployeeWeekID
AND pe.ProjectID = p.ProjectID
AND p.ProjectID = <ausgewähltes Projekt>
Abbildung 47: Ad-hoc-Abfrage über alle Mitarbeiter in einem Projekt in einer ausgewählten Woche
Wie in Kapitel 6.2.7 schon beschrieben wurde, können Select-Anfragen als Sichten abgespeichert werden. Abbildung 48 zeigt eine Sicht, die wiederum eine Sicht
(CurrentEmployeeView ) mit der Tabelle EmployeeAccount verbindet. Die Menge
aller Mitarbeiter mit ihren Accounts, die zum aktuellen Zeitpunkt aktiv sind, wird
dann über ein einfaches
SELECT * FROM EmployeeAccountView
abgefragt.
CREATE VIEW EmployeeAccountView AS
SELECT ...
FROM CurrentEmployeeView, EmployeeAccount
WHERE CurrentEmployeeView.ID=EmployeeAccount.ID
Abbildung 48: Definition einer Sicht auf Mitarbeiteraccounts
Da Sichten nur für Anfragen verwendet werden konnten (siehe Kapitel 6.3.1),
mussten das Ändern, Löschen und Einfügen von Datensätzen in einer Sicht, auf den
in der Sicht enthaltenden Tabellen durchgeführt werden. Ein Beispiel aus der Zeiterfassung ist das in Abbildung 45 dargestellte Beispiel. Ein neu angelegter Mitarbeiter
führt zu einem neuen Eintrag in der Tabelle Employee und für jeden Account zu
einem Eintrag in der Tabelle EmployeeAccount. In Kapitel 6.7.4 wird auf die Problematiken, die bei der Verwendung von Sichten entstehen, noch genauer eingegangen.
6.4.2
Subqueries
Ein Subquery ist ein Query, der in einem anderen Query eingebettet ist (vgl. [Inf 99,
S. 7-60 bis 7-68]). Subqueries können in Insert-, Delete-, Update- und Select-Statements
76
verwendet werden. Ein Beispiel für eine Subquery ist die Anfrage alle Mitarbeiter,
die keinen Vertrag besitzen, wie in Abbildung 49 dargestellt.
(1)
(2)
(3)
(4)
SELECT * FROM Employee e
WHERE (
SELECT COUNT(*) FROM EmployeeContract c
WHERE c.EmployeeID=e.EmployeeID) = ’0’
Abbildung 49: Beispiel aus der Zeiterfassung für einen Subquery
6.4.3
OUTER JOIN
Die bisherigen Verbunde waren so genannte inner join-Verbunde. Ein weiteres Konzept von SQL sind die outer join-Verbunde. Ein outer join-Verbund enthält die
Menge aller inner join-Verbunde. Zusätzlich zu dieser Menge enthält sie die Menge
aller Tupel, die die Bedingungen der Where-Klausel zwar nicht erfüllen, aber aus
einer Tabelle stammen, die in der From-Klausel als outer join definiert wurde.
In Abbildung 50 ist eine Beispielanwendung aus der Zeiterfassung dargestellt,
welche die Liste aller Aufgabenkataloge (Activity) zurückliefert (vgl. dazu auch 55
auf Seite 85).
Existiert zu dem übergebenden Vertrag (contractID) in der übergebenden Woche
(weekID) der übergebenden Fachgruppe (teamID) eine Arbeitszeitzuordnung bzw.
ein Eintrag in der Tabelle ActivityEmployee (siehe Abbildung 55 auf Seite 85), so
wird diese Arbeitszeitzuordnung (Proration) mit ausgegeben.
(1)
(2)
(3)
(4)
(5)
(6)
(7)
(8)
(9)
SELECT *
FROM Activity
OUTER ( ActivityEmployee ActivityEmployee, EmployeeWeek )
WHERE Activity.ActivityID=ActivityEmployee.ActivityID
AND ActivityEmployee.EmployeeWeekID=EmployeeWeek.EmployeeWeekID
AND ( (TeamID is null) OR (TeamID=’“+ teamID + “) )
AND ( (ContractID is null) OR (ContractID=’“+ contractID + “) )
AND ( (WeekID is null) OR (WeekID=’“+ weekID + “) )
AND Activity.ActivityID>’0’
Abbildung 50: Beispiel für outer join
Wie in Abbildung 51 zu sehen ist, existierte für die drei oben angegebenen Parameter für die Fachgruppe ”Software” kein Eintrag. In einem inner join-Verbund
77
wäre die Zeile ”Software” nicht in der Ergebnismenge enthalten gewesen.
Activity.Name
Software
Hardware
Testen
ActivityEmployee.Proration
NULL
77
23
Abbildung 51: Verkürztes Ergebnis der Anfrage aus Abbildung 50
6.5
Redundanzvermeidung durch Normalisierung
Ziel der Normalisierung ist es, ein redundanzfreies Datenmodell zu erhalten, indem
keine unerwünschten Seiteneffekte auftreten. Diese Seiteneffekte werden Anomalien
genannt. Dabei werden die folgenden drei Arten von Anomalien unterschieden:
Update-Anomalie: Änderungen an redundanten Daten müssen an allen vorhandenen Stellen durchgeführt werden.
Insert-Anomalie: Ein Datensatz kann erst eingefügt werden, wenn alle darin enthaltenen Informationen vorhanden sind.
Delete-Anomalie: Wird ein Datensatz gelöscht, so gehen alle Information in diesem verloren.
Durch die von Codd (vgl. Literatur [Cod 70]) vorgestellten Normalformen sollen
diese Anomalien vermieden werden. Das Prinzip der Normalisierung ist es, redundante Daten dadurch zu vermeiden, dass Tabellen aufgeteilt und ggf. über zusätzliche
Schlüssel in Verbindung gesetzt werden. Um die ursprünglichen Relationen wieder
zu erhalten werden diese aufgeteilten Tabellen über ihre Schlüssel verbunden. Die
Zerlegung der Tabellen muss dabei verlustfrei sein, d. h., es dürfen keine Daten
verloren gehen (vgl. auch [Geb 04, S. 167 f.]).
6.5.1
Begrifflichkeiten
Funktionale Abhängigkeit:
Ein Wertebereich B ist funktional abhängig von einem Wertebereich A, geschrieben
A -> B, wenn zu jedem Zeitpunkt gilt:
Zu jedem Wert von A ist genau ein Wert in B zugeordnet. Das bedeutet, dass
der Wertebereich A den Wertebereich B eindeutig identifiziert.
Voll funktionale Abhängigkeit:
Ein Wertebereich B mit B=(B1 , B2 , ..., Bm ) ist voll funktional abhängig von A mit
78
A=(A1 , A2 , ..., An ), wenn B funktional abhängig von A, aber nicht funktional abhängig von einer echten Teilmenge von A ist.
Transitive Abhängigkeiten:
Der Wertebereich C ist funktional abhängig von B und B ist funktional abhängig
von A (A –> B –> C), dann ist C transitiv abhängig von A.
6.5.2
1. Normalform
Eine Relation liegt in der ersten Normalform vor, wenn jedes Attribut atomar ist,
d. h. eine nicht weiter zerlegbare Dateneinheit darstellt und keine Wiederholungsgruppe enthält.
Um eine nicht-normalisierte Relation in eine Relation der ersten Normalform
zu überführen, müssen die nicht atomaren Attribute in atomare aufgeteilt werden.
Die Attribute der Wiederholungsgruppen werden in einer neuen Tabelle angelegt
und entsprechend aus der alten Tabelle entfernt. Anschließend müssen diese beiden
Tabellen über eine Schlüsselverbindung verbunden werden, um die ursprüngliche
Relation wieder darstellen zu können.
Für jeden Wechsel einer Kostenstelle muss ein neuer Datensatz in der Tabelle
Employee erzeugt werden. Dieser enthält ein Datum, ab wann der Mitarbeiter dieser Kostenstelle zugeordnet ist. Die Kostenstelleninformationen dürfen nicht einfach
überschrieben werden, da Reports, die sich auf einen Zeitraum vor dem Wechsel
beziehen, diesen Mitarbeiter mit der vorherigen Kostenstelle darstellen müssen. Ein
Beispiel für solch einen Report wäre eine Stundenübersicht, nach Kostenstellen geordnet, für einen ausgewählten Monat. Das folgende Beispiel soll die Redundanz an
dieser Tabelle zeigen:
Alte Tabelle Employee:
EmployeeID
1
1
2
Name
Vertragsstart Kostenstelle
Claus Schmidt
01.01.2004
287
Claus Schmidt
10.04.2004
110
Max Müller
26.06.1998
287
Wie an dieser Tabelle zu sehen ist, ist Name nicht atomar und Kostenstelle stellt
eine Wiederholungsgruppe dar. Die Konsequenz ist, dass keine Mitarbeiter ohne
Vertrag eingefügt werden können, Änderungen beispielsweise am Namen müssten
an mehreren Stellen durchgeführt werden, und sollten alle Datensätze bzw. Tupel
gelöscht werden, die der Kostenstelle 287 gewesen sind, so wäre die Kostenstelle 287
anschließend nicht mehr existent.
Um diese Relation in die erste Normalform zu überführen, muss der Name in seine
Bestandteile (Vor- und Nachname) zerlegt werden und die Attribute Vertragsstart
79
und Kostenstelle werden in eine neue Tabelle mit dem Namen EmployeeContract
ausgelagert. Zusätzlich ist der neue Schlüssel ContractID nötig, um die ursprüngliche Relation wieder darstellen zu können.
Neue Tabelle Employee:
EmployeeID
1
2
Vorname
Claus
Max
Nachname
Schmidt
Müller
Neue zusätzliche Tabelle EmployeeContract:
EmployeeID
1
1
2
ContractID Vertragsstart Kostenstelle
1
01.01.2004
287
2
10.04.2004
110
1
26.06.1998
287
Durch den dargestellten Normalisierungsprozess ergab sich, dass ein Mitarbeiter
eine beliebige Menge an Verträgen besitzt, wobei es in dem jetzigen System nicht
möglich ist, dass ein Mitarbeiter mehr als einen Vertrag gleichzeitig besitzt, was aber
im Datenmodell ohne größere Probleme möglich wäre.
Wie an diesem Beispiel zu sehen ist, hilft Normalisierung nicht nur Redundanzen
zu vermeiden bzw. zu mindern, sondern hilft auch die Daten und ihre Abhängigkeiten besser zu verstehen. Diese Information, dass Mitarbeiter Verträge besitzen und
eigentlich nur die Verträge ”arbeiten”, d. h. Arbeitszeiten besitzen und diese Zeiten
auf Projekte verteilen, wurde im Requirement Engineering ”übersehen” und ist erst
beim Normalisieren entstanden.
6.5.3
2. Normalform
Eine Relation liegt in der zweiten Normalform vor, wenn sie in der ersten Normalform vorliegt und jedes Nichtschlüsselattribut16 voll funktional abhängig vom
Primärschlüssel ist (vgl. [CIS]).
Das bedeutet, dass es keine Nichtschlüsselattribute geben darf, die nur von einem
Teil des Primärschlüssels abhängig sind (vgl. gestrichelte Linie in Abbildung 52).
Alte Tabelle Week:
16
Attribute, die nicht zum Primärschlüssel gehören
80
Abbildung 52: Grafische Darstellung der 2NF
WeekID ContractID Year CalendarWeek WorkingHour
1
1
2004
10
38
1
2
2004
13
45
Neue Tabelle Week:
WeekID Year CalendarWeek
1
2004
10
1
2004
13
Neue zusätzliche Tabelle EmployeeWeek:
WeekID ContractID WorkingHour
1
1
38
1
2
45
6.5.4
3. Normalform
Eine Relation liegt in der dritten Normalform vor, wenn sie sich in der 2. Normalform
befindet und jedes Nichtschlüsselattribut nicht transitiv abhängig vom Primärschlüssel ist (vgl. [CIS]).
Es würfen keine Nichtschlüsselattribute existieren, die von einem anderen Nichtschlüsselattribut abhängig sind (vgl. gestrichelte Linie in Abbildung 53).
Abbildung 53: Grafische Darstellung der 3NF
Alte Tabelle Project:
PjID PjName
10001
Joker
10002 Frankit
PjTypeName
Frankiermaschine
Frankiermaschine
81
PjTypeFirstPjID
10000
10000
Neue Tabelle Project:
PjID PjName
10001
Joker
10002 Frankit
PjTypeID
1
1
Neue zusätzliche Tabelle ProjectType:
PjTypeID
PjTypeName
1
Frankiermaschine
6.5.5
PjTypeFirstPjID
10000
Boyce-Codd-Normalform (BCNF)
Eine Relation befindet sich in der BCNF genau dann, wenn sie in der 3NF vorliegt
und alle voll funktionalen Abhängigkeiten vom Primärschlüssel ausgehen (vgl. [CIS]).
Das bedeutet, dass kein Nichtschlüsselattribut ein Primärschlüsselattribut identifizieren darf (vgl. gestrichelte Linie in Abbildung 54).
Abbildung 54: Grafische Darstellung der BCNF
6.6
ODBC-Schnittstelle
ODBC steht für Open DataBase Connectivity und ist eine standardisierte Schnittstelle, die durch standardisierte Methoden den Zugriff einer beliebigen Applikation
auf eine beliebige (relationale) Datenbank beschreibt (vgl. [MSDN]).
Im .NET-Framework werden hierfür Klassen zur Verfügung gestellt, die diese
Methoden anbieten und somit die Anwendung unabhängig von der spezifischen (relationalen) Datenbank machen. Die vier wichtigen Klasen im .NET-Framework sind
dabei folgende:
OdbcConnection: Reräsentiert eine Datenbankverbindung.
OdbcCommand: Repräsentiert einen SQL-Query oder eine benutzerdefinierte Routine (vgl. Kapitel 6.2.6).
OdbcDataReader: Repräsentiert eine Ergebnisrelation, die durch einen SQL-Query
zurückgeliefert wurde.
82
OdbcTransaction: Repräsentiert eine Transaktion.
Durch die Verwendung von ODBC-Klassen im .NET Framework werden die Probleme mit den heterogenen Datenbanken gemindert. Das Definieren von Transaktionen mit entsprechenden Einstellungen für die Nebenläufigkeitskontrolle (vgl. 6.3.4)
und der Verbindungsaufbau zur Datenbank werden durch die ODBC-Klassen durchgeführt. Die Nebenläufigkeitsanomalie Phantom Read (vgl. 6.3.3) kann allerdings nur
durch Serialisieren der Transaktionen vermieden werden.
6.7
6.7.1
Konkrete Implementierung
Verwendete Modellierungstechnik
Zur Beschreibung des Datenmodells habe ich die IDEF1X-Notation gewählt, da
das mir zur Verfügung stehende Tool ERwin17 diese Notation verwendet. Auf einer grafischen Benutzeroberfläche lassen sich damit Entitäten und ihre Beziehungen
darstellen. Aus diesen Modellen können SQL-Scripte erzeugt werden, welche die Datenbankstruktur erzeugen.
IDEF1X (siehe [IDEF]) ist eine Datenmodellierungssprache, welche auf dem Ansatz des Entity-Relationship-Modells (ER-Modell) basiert und außerdem Konzepte
des Relationenmodells von [Cod 70] enthält. Ziel dieser Modellierungsform ist eine
bessere grafische Repräsentation (siehe [Ade 94, S. 9 f.]).
Genauso wie in einem ER-Modell werden Entitäten durch Rechtecke dargestellt.
Die Attribute werden dabei direkt in die Rechtecke hineingeschrieben, wie in Abbildung 55 auf Seite 85 zu sehen ist. Die so genannten schwachen Entitäten (siehe
[Vor 99, S. 22 f.]) im ER-Modell werden im IDEF1X-Modell als abhängige bezeichnet und durch ein Recheck mit abgerundeten Ecken dargestellt. Diese Entitäten
ergeben nur zusammen mit einer unabhängigen Entität eine Information, so wie in
Abbildung 55 auf Seite 85 die Entitäten Klassen ProjectEmployee, TeamEmployee
und ActivityEmployee.
Vererbung wird zwar im IDEF1X-Modell unterstützt, kann aber weder im ERwin noch in der relationalen Datenbank realisiert werden (siehe [Ett 99, S. 41 bis 47]).
Die Primärschlüssel werden am oberen Ende einer Entität dargestellt und durch
eine horizontale Linie von den übrigen Attributen getrennt. Fremdschlüsselattribute
werden durch das Kürzel (FS) dargestellt.
Während das ER-Diagramm nur die Abhängigkeiten beschreibt und Primärschlüssel definiert, werden diese in dem IDEF1X-Modell genauer spezifiziert. Bei den
17
r
siehe Homepage von Computer Associates
: http://www.ca.com
83
Beziehungen zwischen den Entitäten werden zwei Arten unterschieden: identifizierende und nicht-identifizierende. Bei einer identifizierenden Beziehung ist der Fremdschlüssel gleichzeitig ein Primärschlüssel, während bei einer nicht-identifizierenden
Beziehung dies nicht der Fall ist.
Ein Beispiel für eine identifizierende Verbindung ist die Verbindung zwischen
Employee und EmployeeAccount in Abbildung 55. Das Primärschlüsselattribut EmployeeID in der Entität EmployeeAccount ist gleichzeitig der Fremdschlüssel zum
Primärschlüsselattribut EmployeeID in Employee.
In den meisten Fällen wurden in der Zeiterfassung nicht-identifizierende Beziehungen gewählt und ein entsprechend neuer Primärschlüssel wurde angelegt. Damit
besitzt fast jede Entität nur einen Primärschlüssel und Abhängigkeiten zwischen den
Primärschlüsseln können gar nicht erst auftreten. Weitere Gründe werden in Kapitel
6.7.5 aufgeführt. Nicht-identifizierende Beziehungen werden durch eine gestrichelte
Linie dargestellt. Der ausgefüllte Punkt am Ende einer Beziehungslinie beschreibt,
welche Entität durch einen Fremdschlüssel mit der dazugehörigen Entität verbunden ist. Der nicht ausgefüllte Punkt, wie in Abbildung 55 an der Beziehung zwischen
Employee und ProjectTeam zu sehen ist, bedeutet, dass der Fremdschlüssel auch den
Wert NULL besitzen darf, was sonst nicht der Fall ist.
Das Tool ERwin bietet außerdem die Möglichkeit, die referenziellen Aktionen für
das Einfügen (I-nsert), Ändern (U-pdate) und Löschen (D-elete) darzustellen. Dabei
sind die in Kapitel 6.2.4 beschriebenen fünf Einstellungen möglich, wobei nur Schlüsselverbindungen, die auch Null sein dürfen, auf Set Null gesetzt werden dürfen. Der
Ausdruck D:C bedeutet beispielsweise, dass das Löschen eines Datensatzes kaskadiert wird (siehe Kapitel 6.2.4), d. h., das Löschen eines Mitarbeiters (Employee)
führt zu einem Löschen aller seiner Accounts (EmployeeAccount) (siehe Abbildung
55).
6.7.2
Entwurf des Datenmodells
In diesem Abschnitt wird an einigen Beispielen gezeigt, welche konkreten Probleme
sich bei der Entwicklung des relationalen Datenmodells ergeben haben und wie diese
gelöst wurden. Wie bereits in Abbildung 55 zu sehen ist, ist die Struktur der Entitäten nicht ohne weiteres ersichtlich. Während in einem Klassenmodell Konzepte
zur Verfügung gestellt werden, mit denen Beschreibungen der Realität im Modell
abgebildet werden können (vgl. [Fra+ 96, 2.Kapitel]), können diese nicht direkt abgebildet werden. Beispielsweise ist ein externer Mitarbeiter eine spezielle Form eines
Mitarbeiters und kann durch Vererbung im Klassenmodell auch so modelliert werden. Diese Möglichkeit bietet das relationale Datenmodell nicht.
Ein weiteres Problem ist das Fehlen der Aggregationsbeziehung. Im Klassen84
modell von Abbildung 8 auf Seite 28 ist die Verbindung von Projekt (Project) zu
Fachgruppe (ProjectTeam) eine Aggregation, d. h., ein Projekt besitzt Fachgruppen (siehe auch [Bit Koc 00, S.18 f.]). Diese Modellierungsform ist in IDEF1X nicht
möglich (siehe [Ett 99, S. 48]).
Eine Kompositionsbeziehung abzubilden, so wie sie in Abbildung 8 auf Seite 28
zwischen Mitarbeiter und Account besteht, ist in IDEF1X ebenfalls nicht möglich
(siehe [Ett 99, S. 49]). Es besteht lediglich die Möglichkeit, diese über die Fremdschlüsseleigenschaften nachzubilden (siehe Kapitel 6.2.4). Wie in Abbildung 55, an
der Verbindung zwischen Employee und EmployeeAccount zu sehen ist, wurde diese
als Delete Cascade (D:C) gekennzeichnet.
Abbildung 55: Datenmodell nach der IDEF1X-Notation (siehe Kapitel 6.7.1)
85
Das Datenmodell wurde direkt im ERwin erstellt. Ein Entwurf mit einem Klassenmodell hätte dazu verführt, durch zu viele Klassen und Vererbung eine Struktur
zu entwerfen, die im IDEF1X-Modell, was von ERwin unterstützt wird, sehr unübersichtlich geworden wäre. In Kapitel 6.8.2 wird dieses Problem an einem Beispiel
gezeigt.
Kalenderwochen und Mitarbeiter
Bei der Analyse mit Requirements Engineering (siehe Mitarbeiter in Kapitel 3.1.4
und Kapitel 3.1.2) und im Entwurf (siehe Kapitel 5.3.5) wurden lediglich Wochen
bzw. Kalenderwochen erwähnt. Im Datenmodell müssen diese mit abgespeichert
werden (siehe Week ), da Mitarbeiterwochen (siehe EmployeeWeek ) von diesen abhängig sind. Außerdem besitzen Wochen zwei zusätzliche Flags, die identifizieren, ob
eine Kalenderwoche für interne bzw. externe Mitarbeiter bereits abgerechnet wurde, wobei hier nur von Vertragsmitarbeitern die Rede ist, d. h. Mitarbeitern, die in
Projekten arbeiten und ihre Zeiten den Projekten zuordnen müssen.
Bei den Vertragsmitarbeitern gibt es zwei Arten: interne und externe. Interne
Mitarbeiter unterteilen sich wiederum in ”normale” interne Mitarbeiter, Studenten
und Aushilfen. Da das relationale Datenmodell keine Vererbung anbietet, die Tabellen aber noch die Entitäten widerspiegeln sollen, wurde das Problem wie folgt gelöst:
Externe Mitarbeiter besitzen in ihren Verträgen die EmployeeTypeID null. Eine
EmployeeTypeID größer Null definiert einen internen Mitarbeiter, wobei in der Tabelle EmployeeType die verschiedenen Arten der internen Mitarbeiter (Stundenten,
Aushilfen und ”normale interne Mitarbeiter”) abgespeichert werden. Damit ist die
Liste der internen Mitarbeitertypen beliebig erweiterbar.
Mitarbeiter und ihre Verträge
Jeder Vertragsmitarbeiter besitzt eine beliebige Menge an Verträgen. Diese Verträge besitzen für jede Kalenderwoche Arbeitszeiten. Jede Vertragsmitarbeiterwoche (EmployeeWeek ) kann durch Setzen des Flags Finish geschlossen werden. In
diesem Fall dürfen keine Zuordnungen der Arbeitszeiten zu Projekten, Fachgruppen
oder Aufgabenkatalogen durchgeführt werden. Die Verträge der Vertragsmitarbeiter
dürfen sich nicht überschneiden, da jeder Vertragsmitarbeiter zu jedem Zeitpunkt
nur einen Vertrag besitzen darf. Mitarbeiter, die aus Sicht der Zeiterfassung keine
Verträge besitzen, dürfen zwar Projektleiter oder Fachsprecher sein, besitzen aber
entsprechend keine Einträge in der Tabelle EmployeeContract, wie in Abbildung 55
zu sehen ist.
Projekte und Fachgruppen
86
Jedes Projekt besitzt eine beliebige Menge an Fachgruppen. Auch in diesem Fall
gibt es zwei Arten von Projekten: Projekte mit Fachgruppen und Projekte ohne.
Bei Projekten ohne Fachgruppen müssen aber ebenfalls Zuordnungen nach Aufgabenkategorien vorgenommen werden. Ein Eintrag in der Tabelle ActivityEmployee
muss jedoch von einem ProjectTeam abhängig sein. Um keine weiteren Tabellen einzufügen, besitzt jedes Projekt eine Default-Fachgruppe, die dadurch gekennzeichnet
ist, dass sie keinen Fachsprecher besitzt. Zeitzuordnungen auf Aufgabenkataloge in
Projekten, die keine Fachgruppe besitzen, werden auf diese Default-Fachgruppe geschrieben. In den Ausgaben wird diese Fachgruppe unter dem Namen ”Sonstige
Fachgruppen” dargestellt.
Arbeitszeitzuordnungen auf Projekte, Fachgruppen und Aufgabenkatalog
Die Zuordnungen der Arbeitszeiten zu den Projekten, Fachgruppen und Aufgabenkatalogen werden in den Tabellen ProjectEmployee, TeamEmployee und ActivityEmployee abgespeichert. Ein Überblick über beispielsweise einen Mitarbeiter
in einer ausgewählten Kalenderwoche ist nur über mehrere Anfragen möglich. Im
weiteren Verlauf wird noch gezeigt, wie dieses Problem in einer objektorientierten
Datenbank besser gelöst werden kann.
Zunächst wird die Mitarbeiterwoche (EmployeeWeek ) ermittelt. Für eine ausgewählte Kalenderwoche und einen ausgewählten Mitarbeiter wird diese durch einen
Verbund von Employee, EmployeeContract, EmployeeWeek und Week ermittelt.
Anschließend müssen, abhängig von EmployeeWeek, die darin enthaltenen Projekte (ProjectEmployee und Project) bestimmt werden. Für jedes Projekt wird die
Liste aller zugeordneten Fachgruppen (TeamEmployee und ProjectTeam) und die
darin enthaltenen Aufgabenkataloge (ActivityEmployee und Activity) ausgelesen.
6.7.3
(SQL-)Transaktionen
Der Zugriff auf die relationale Datenbank erfolgt in der Zeiterfassung über eine
Instanz der Klasse Database, wie in Abbildung 56 dargestellt, welche die ODBCSchnittstelle bzw. die ODBC-Klassen von .NET verwendet.
Beim Erzeugen einer Instanz dieser Klasse wird eine serialisierte Transaktion geöffnet, die beim Entfernen dieser Instanz wieder geschlossen wird. Wie in Kapitel
6.3.4 schon beschrieben wurde, gibt es in einer relationalen Datenbank keine wirklich
brauchbare Lösung, um eine optimistische Nebenläufigkeitskontrolle durchzuführen.
In Kapitel 6.3.3 wurde gezeigt, dass das Phantom Read durchaus ein Problem darstellt.
87
Abbildung 56: Klasse Database
Durch Serialisieren der Transaktionen ist dieses Problem gelöst. Da Performanz
und eine hohe Last bei der Zeiterfassung keine allzu wichtigen Themen sind, kann
diese Lösung auch hingenommen werden. Bei einem Fehler, weil beispielsweise ein
Lock gesetzt ist, wird eine Exception geworfen, die entsprechend abgefangen werden
muss.
In Abbildung 57 ist ein Beispiel für eine Anwendung dieser Klasse dargestellt.
Die getData-Methoden (siehe Abbildung 56) geben nach einem gesendeten Query
(siehe db.Query) die gewünschten Attribute eines Tupels zurück. In der ODCBKlasse OdbcDataReader können die Attribute nur über die Spaltennummer abgefragt werden, da es aber sinnvoller ist, diese über ihren Namen (in Abbildung 57,
Zeile 5 ”name”) zu identifizieren, werden in den getData-Methoden entsprechende
Umwandlungen vorgenommen. Der Vorteil dieser Variante ist die Unabhängigkeit
zu Odbc. Ein Austauschen der (relationalen) Datenbank, für die beispielsweise kein
Odbc-Treiber existiert, hätte nur eine Änderung an dieser Klasse zur Folge. Das
Protokollieren von gesendeten Queries beispielsweise müsste ebenfalls nur an dieser
Klasse, genauer gesagt in der Methode Query, durchgeführt werden.
88
(1)
(2)
(3)
(4)
(5)
...
(6)
(7)
Database db = new Database() );
db.Query( ”SELECT * FROM CostCenter ORDER BY CostCenterID” );
while( db.getNextRecord() ){
CostCenter data = (CostCenter)this.CreateObject();
data.Name = db.getData(”name”);
}
db.Dispose(); // zum Beenden einer Transaktion
Abbildung 57: Beispielanwendung für die Klasse Database ohne Ausnahmebehandlung
6.7.4
Sichten
Unabhängige Entitäten besitzen allein betrachtet keine sinnvollen Informationen und
müssen mit abhängigen verbunden werden. Die abhängigen Entitäten können aber
ebenfalls nicht sinnvoll allein betrachtet werden.
Für die Anfragen nach einer Menge von Projekten werden beispielsweise auch die
Namen der zugehörigen Projektleiter, Projekttypen und Projektgruppen benötigt.
Aus diesem Grund wurden, wie in Abbildung 58 zu sehen ist, Sichten für verschiedene Entitäten definiert. Die verwendete Namenskonvention ist dabei ”<Tabellenname>View”.
Sicht
EmployeeAccountView
EmployeeView
EmployeeWeekView
ProjectTeamView
ProjectView
ProjectEmployeeView
TeamEmployeeView
ActivityEmployeeView
CurrentEmployee
Zusätzliche Tabellen bzw. Sichten
EmployeeView
EmployeeContract, EmployeeType u. CostCenter
Employee u. EmployeeContract
Project u. Employee
ProjectType, ProjectGroup, Employee u. ProjectTeam
Project u. EmployeeWeek
ProjectTeam u. EmployeeWeek
Activity u. EmployeeWeek
EmployeeView mit Einschränkung
Abbildung 58: Sichten aus der Zeiterfassung
Für Anfragen sind Sichten ein vorteilhaftes Konzept, um die Anfragen zu vereinfachen, wie in Abbildung 58 zu sehen ist.
Das Löschen von abhängigen Entitäten kann dabei kaskadiert werden, wie dies
beispielsweise bei Employee und EmployeeAccount der Fall ist. Wird ein Mitarbeiter
89
gelöscht, so werden alle dazugehörigen Accounts mit gelöscht.
Beim Einfügen und Ändern von Entitäten ist dies etwas schwieriger. Wie bereits in Kapitel 6.2.7 erwähnt wurde, bestand keine Möglichkeit, in den Sichten
Datensätze einzufügen oder diese zu ändern. In Abbildung 59 ist die Eingabemaske
für Vertragsmitarbeiter zu erkennen. Wie dort zu sehen ist, werden Mitarbeiter-,
Vertrags- und Accountdaten erfasst. Das Einfügen eines Vertragsmitarbeiters erstreckt sich in diesem Fall über die drei Tabellen Employee, EmployeeAccount und
EmployeeContract.
Abbildung 59: Screenshot: Eingabemaske der Vertragsmitarbeiter
6.7.5
Primärschlüssel und Identität
Ein Problem bei der Datenmodellierung stellte die Definition der Primärschlüssel
dar. Eine Komposition beispielsweise kann als eine identifizierende Verbindung zwischen zwei Entitäten modelliert werden, wobei die Fremdschlüssel gleich dem Primärschlüssel sind (vgl. [Ade 94, S. 13]).
Ein Beispiel ist die Verbindung zwischen Fachgruppe und Projekt in Abbildung
8 auf Seite 28. Ein Projekt kann nur existieren, wenn die dazugehörige Fachgruppe
existiert. Die Verbindung zwischen Fachgruppe und Projekt ist ebenfalls eine Komposition, d. h., diese Verbindungen können als identifizierende modelliert werden.
Das Resultat war, dass eine Fachgruppe von den drei Schlüsseln, der Projektgruppe,
dem Projekt und der Fachgruppe, abhängig war, d. h. einen zusammengesetzten
90
Primärschlüssel aus diesen drei Attributen besaß, wie in Abbildung 60 zu sehen ist.
Abbildung 60: zusammengesetzter Primärschlüssel
Dies stellt aber eine Verletzung der zweiten Normalform dar, da es keinen Unterschied macht, ob für die Identifizierung eines Datensatzes aus ProjectTeam das
Attribut ProjectGroupID verwendet wird oder nicht. Aus diesem Grund wurde die
Verbindung zwischen Projekt und Projektgruppe in eine nicht-identifizierende geändert. Ein weiteres Problem ist, dass sich bei identifizierenden Verbindungen die
Schlüsseldefinition ”ausbreitet”, d. h. wenn ein Projekt beispielsweise nicht mehr
durch eine Projektgruppe identifiziert wird, so würde das Löschen der Projektgruppe zu einer geänderten Definition in der Tabelle ProjectTeam führen. Das Primärschlüsselattribut ProjectGroupID wird dann in ProjectTeam ebenfalls gelöscht, obwohl keine direkte Verbindung zwischen ProjectTeam und ProjectGroup besteht.
Ein weiteres Problem stellte die Tatsache dar, dass eine Entität, die durch mehr
als ein Attribut im Primärschlüssel identifiziert wird, keine automatisch erzeugten
Primärschlüssel (vgl. mit serial in Kapitel 6.2.2) erzeugen kann, d. h., der Primärschlüssel hätte manuell erzeugt werden müssen. Da sich die Anforderungen einige
Male geändert haben (vgl. mit Prototyping in Kapitel 3.1.5), wurde dazu übergegangen, für jede Entität nur ein Attribut als Primärschlüssel zu verwenden und die
Verbindungen zwischen Entitäten durch nicht-identifizierende zu ersetzen.
Das Problem mit den Projektnummern, die als Primärschlüssel verwendet werden, wurde bereits in Kapitel 6.2.2 beschrieben.
Aus diesem Grund wurde fast überall ein technischer Schlüssel eingeführt, der
sozusagen die Objektidentität simulieren soll. Dieser ist in jeder Tabelle eindeutig
und vom Anwender nicht änderbar bzw. sollte nicht geändert werden.
6.7.6
Referenzielle Integrität
Die referenzielle Integrität verhindert, dass eine Datenbank in einen inkonsistenten
Zustand kommen kann, wie in Abbildung 61 an einigen Beispielen für Projekt und
91
Projekttyp dargestellt ist. Komplexe Integritätsprüfungen können nur über Trigger
realisiert werden, wobei die fehlende Kapslung hier ein Problem darstellt. Dadurch,
dass an jeder beliebigen Stelle in der Datenbank Änderungen vorgenommen werden
können, müssen verschiedenste Trigger an allen möglichen Stellen eingeführt werden.
Änderungen an den Tabellen hätten Änderungen an den entsprechenden Triggern
zur Folge, wobei die Abhängigkeiten und Integritätsprüfungen ziemlich schnell sehr
komplex und unübersichtlich werden können. Das folgende Beispiel soll dies verdeutlichen:
Eine Mitarbeiterwoche (EmployeeWeek ) darf nur dann den Zustand Finish=True
besitzen, wenn bestimmte Voraussetzungen der Tabellen ProjectEmployee, TeamEmployee und ActivityEmployee erfüllt sind. Da diese drei Tabellen durch die fehlende
Kapselung beliebig geändert und gelöscht werden können, müssen in diesen Tabellen
ebenfalls entsprechende Überprüfungen vorgenommen werden. Dieses Datenmodell
ist noch relativ einfach. Bei größeren Modellen, an denen mehrere Entwickler beteiligt sind, kann dies zu einem großen Problem werden, wenn sich die Abhängigkeiten
über mehrere Tabellen erstrecken.
• Ein Projekt kann keinem Projekttyp zugeordnet werden, welcher nicht existiert.
• Ein Projekttyp kann nur gelöscht werden, wenn kein Projekt auf dieses Projekt
verweist.
• Ein Projekt, das eingefügt wird, muss auf einen gültigen Projekttypen verweisen.
Abbildung 61: Beispiel für referenzielle Intrität zwischen Projekt und Projekttyp
6.8
6.8.1
Motivation zur Objektorientierung in Datenbanken
Vorteile einer relationalen Datenbank
Die relationale Datenbank bietet trotz der vielen Schwächen eine Reihe von Vorteilen, wie in Abbildung 62 zu sehen ist, wobei sich die letzten beiden Punkte auf
die Tatsache beziehen, dass Daten in Tabellen abgespeichert werden und auf diese
einfach zugegriffen werden kann. Wie schon gezeigt wurde, ist der Zugriff auf die
Informationen, die durch die Beziehungen der Tabellen untereinander dargestellt
werden, teilweise nur mit sehr komplizierten Queries möglich.
92
• In der Regel sind relationale Datenbanken auch bei sehr großen Datenmengen
noch sehr leistungsstark.
• Die relationalen Datenbanken werden in der Regel von großen Firmen entwickelt, die viel Erfahrung auf diesem Gebiet besitzen.
• Relationale Datenbanken haben sich in der Vergangenheit schon mehrfach bewährt.
• Durch Normalisierung wird Redundanz vermieden oder wenigstens gemindert.
• Durch mathematische Regeln lassen sich die Abhängigkeiten, Einschränkungen und Bedingungen der Daten beschreiben und müssen nicht implementiert
werden.
• Durch den SQL-Standard besteht (zumindest theoretisch) eine Unabhängigkeit
von Anwendung und Datenbank [Saa 03, S. 35].
• Ein relationales Datenmodell hat eine einfache Struktur (Tabellen und Schlüsselverbindungen).
• Über ein entsprechendes Tool und SQL kann in einer relativ einfachen Form
auf die Daten zugegriffen werden.
Abbildung 62: Vorteile einer relationalen Datenbank
6.8.2
Nachteile einer relationalen Datenbank
Anhand eines konkreten Beispiels sollen die Probleme des relationalen Datenmodells
erklärt werden. Die Beschreibungen basieren auf dem Datenmodell von Abbildung
55. Wie in Abbildung 63 zu sehen ist, gibt es zwei Arten von Mitarbeitern, die im
Folgenden kurz erklärt werden.
Mitarbeiter, die keinen Vertrag besitzen (Employee) (vgl. Kapitel 6.7.2), können
Projektleiter (projectLeader ) in einem Projekt und Fachsprecher (teamLeader ) in
einer Fachgruppe sein. Außerdem besitzen sie Benutzerrechte (EmployeeRole) und
einen Namen (EmployeeName). Mitarbeiter, die bereits Fachsprecher oder Projektleiter gewesen sind, dürfen nicht gelöscht werden, da beispielsweise Statistiken über
vergangene Projekte oder Fachgruppen die richtigen Projektleiter und Fachsprecher
enthalten müssen. Diese werden durch Löschen eines Flags ( active) als nicht aktiv
gekennzeichnet. In dem Beispiel von Abbildung 63 wird dieses Flag über die Methoden SetActive und GetActive gesetzt bzw. gelesen.
Vertragsmitarbeiter (EmployeeWithContract) besitzen zusätzlich Verträge. Die
93
Abbildung 63: Nachteile eines relationalen Datenmodels anhand eines Beispiels
Unterscheidung zwischen diesen beiden Mitarbeitertypen wird in dem relationalen
Datenmodell über einen Subquery realisiert, der prüft, ob der entsprechende Mitarbeiter mindestens einen Vertrag besitzt. In der Variante von Abbildung 63 ist diese
mühselige Anfrage nicht nötig. Außerdem werden Mitarbeiter, die mindestens einen
Vertrag besitzen, beim Löschen anders behandelt. Beim Löschen wird der aktuelle
Vertrag beendet. In der Variante von Abbildung 63 wird diese Funktionalität durch
Überschreiben der Methoden realisiert.
In Abbildung 55 besitzt die Tabelle Employee ein Flag active. Dieses hat für
Vertragsmitarbeiter keine direkte Bedeutung. Um die Struktur des Datenmodells
übersichtlich zu halten, wurde diese Schwäche hingenommen.
Die Datentypen der Attribute müssen atomar sein, d. h., komplexe Datentypen,
wie im Klassenmodell z. B. durch Vererbung möglich sind, müssen in anderer Form
abgebildet werden. Wie in Abbildung 55 zu sehen ist, ist die Unterscheidung von
Mitarbeitern mit und Mitarbeitern ohne Vertrag nicht sofort ersichtlich.
Um die Trennung der Klassen Employee, EmployeeName und EmployeeRole in
dem relationalen Datenmodell zu realisieren, wären zusätzliche Tabellen und Fremdschlüsselverbindungen nötig, welche die Mitarbeiteranfragen weiter verkomplizieren
würden.
Die Entitäten eines relationalen Datenmodells enthalten keine Funktionalitäten.
Es besteht zwar die Möglichkeit, Funktionalität über benutzerdefinierte Routinen zu
definieren, allerdings können diese nicht direkt an die Entitäten gebunden werden
und nur einfache Datentypen zurückliefern. Eine benutzerdefinierte Routine, die alle
94
Mitarbeiter zurückliefert, die eine bestimmte Bedingung erfüllen, ist beispielsweise
nicht möglich.
Das Problem mit den Primärschlüsseln und den Identitäten wurde bereits in Kapitel 6.7.5 beschrieben.
Durch die fehlende Kapselung (vgl. Kapitel 6.7.6) besteht keine Trennung von
Schnittstelle und Realisierung, d. h., Daten können beliebig auf allen Tabellen geändert werden. Komplexe Integritätsprüfungen durch z. B. Trigger müssen alle denkbaren Fälle abfangen. Eine Entwicklung eines sehr großen Datenmodells von mehreren
Entwicklern ist nur mit sehr viel Aufwand möglich. Ein Datenmodell in mehrere
Teile zu zerlegen und nur über fest definierte Schnittstellen miteinander zu kommunizieren kann zwar vereinbart werden, wird aber in der Datenbank nicht unterstützt.
6.8.3
Object-Oriented Database System Manifesto
Im Object-Oriented Database System Manifesto von 1995 [Atk+ 95] wurden die
Anforderungen untersucht, die eine objektorientierte Datenbank erfüllen muss. Die
Eigenschaften lassen sich in zwei Gruppen einteilen. Zum einen wurden die Anforderungen an eine objektorientierte Programmiersprache und zum anderen die Anforderungen an eine Datenbank untersucht. Eine ”gute” objektorientierte Datenbank
sollte all diese Anforderungen erfüllen.
Objektorientierte Eigenschaften:
Komplexe Datentypen: Komplexe Datentypen müssen sich mithilfe von Konstruktoren aus einfachen (atomaren) Datentypen, wie zum Beispiel integer,
boolean oder string, zusammensetzen lassen. Des Weiteren soll es verschiedene Arten von komplexen Konstruktoren, wie zum Beispiele Tupel, Set, Bag,
Listen oder Arrays, geben. Die Objektkonstruktoren müssen orthogonal sein,
d. h., jeder Konstruktor muss an jedes Objekt anwendbar sein.
Objektidentität: Jedes Objekt muss eine eindeutige und von den Attributen
unabhängige Identität besitzen, die systemweit (oder wenigstens datenbankweit) gültig ist. Damit können zwei Arten von Objektgleichheit unterschieden
werden: identisch (das gleiche Objekt) und gleich (gleiche Werte, aber unterschiedliche Identität).
Kapselung: Kapselung verhindert unzulässige Zustandsänderungen und verbirgt
den Implementierungsteil. Damit entsteht eine saubere Trennung zwischen
Schnittstelle und Implementierung und Änderungen in der internen Struktur
werden nach außen nicht sichtbar.
95
Typen oder Klassen: Ein Typ in einem objektorientierten System fasst Objekte
mit gleichen Eigenschaften zusammen. Dieser besteht auf einem Interface und
der Implementierung. Nach außen sichtbar ist nur das Interface und die Implementierung bleibt dem Anwender diese Typs verborgen. Die Implementierung
besteht aus Daten und Funktionalitäten.
Eine Klasse wird zwar genauso wie ein Typ definiert, bietet aber noch zwei
weitere Aspekte: Objekterzeugung und Objektcontainer. Durch einen new Operator werden Instanzen eines Objekts erzeugt und über den Objektcontainer können Operationen auf einer Menge aller Objekte dieser Klasse durchgeführt werden.
Vererbung: Vererbung und Klassenhierarchien sollen möglich sein, um Attribute
und Methoden wiederzuverwenden, zu erweitern, zu überschreiben oder zu
spezialisieren.
Overriding, Polymorphismus und dynamisches Binden:
Overloading bedeutet, dass verschiedene Methoden mit gleichem Namen und unterschiedlichen Parametern definiert werden. Beim Aufruf einer Methoden wird anhand
der Parameter entschieden, welche Implementierung verwendet wird.
Durch Overriding wird dynamisches Binden möglich. In einer vererbten Klasse
wird eine Methode überschrieben, d. h., die Implementierung wird geändert.
Damit wird zur Laufzeit entschieden (late binding), welche Implementierung
verwendet wird.
Sprach- und Berechnungsvollständigkeit: Man kann jede berechenbare Funktion ausdrücken, was in SQL nicht vollständig möglich ist.
Erweiterbarkeit von Typen: Das Datenbanksystem hat eine vordefinierte Menge von Datentypen, die verwendet werden können. Des Weiteren soll es aber
auch möglich sein, neue Typen zu definieren, die nicht von den vordefinierten
Typen unterschieden werden können.
Datenbankeigenschaften:
Persistenz: Die Lebensdauer eines Objektes soll länger sein als die Lebensdauer einer Applikation und soll im gleichen Zustand in einem weiteren Prozess
verwendet werden können.
(sekundäres) Datenmanagement: Sekundäres Datenmanagement ist eine Ansammlung von Mechanismen, die für den Anwender der Datenbank nicht sichtbar sind und z. B. die Performanz verbessern sollen. Diese sind z. B. Indizierung, Pufferung, Zugriffsmanagement, Daten-Cluster oder Queryoptimierung.
Es wird gefordert, dass der Anwender keinen zusätzlichen Code schreiben muss,
um z. B. einen Index aktuell zu halten o. Ä., d. h., es soll eine Trennung zwischen der logischen und physikalischen Ebene des Systems geben.
96
Nebenläufigkeit: Mehrere Benutzer sollen parallel auf einer Datenbank arbeiten
können, ohne dass es zu inkonsistenten Zuständen kommt. Diese Eigenschaft
beschreibt im Wesentlichen die Problematik, die schon in Kapitel 6.3.3 beschrieben wurde.
Recovery: Im Falle eines Ausfalls durch einen Hardware- oder Softwarefehler,
muss eine Rekonstruktion des alten und konsistenten Zustandes möglich sein.
Ad hoc Abfragemöglichkeit: Durch eine einfach Anfragesprache soll es möglich
sein, Inhalte aus der Datenbank auszulesen. Die Anfragesprache sollte dabei
folgende Bedingungen erfüllen:
1. Sie sollte einfach sein, bzw. es sollte möglich sein, in kurzen Anfragen
Informationenen erhalten.
2. Sie sollte effizient sein (z. B. durch Query-Optimierung).
3. Sie sollte unabhängig von der Applikation sein, d. h., die Anfragesprache
sollte auf jeder möglichen Datenbank gleichermaßen funktionieren.
Diese Anforderungen werden im folgenden Kapitel anhand einer objektrelationalen Datenbank untersucht. Bei der objektrelationalen Datenbank wird von einer
SQL-99-komformen Datenbank ausgegangen, d. h., es wird geprüft, inwieweit eine
Datenbank, die diesem Standard entspricht, die gestellten Anforderungen erfüllt.
Den Abschluss bildet ein kurzer Überblick über die Möglichkeiten mit einer objektorientierten Datenbank. Dabei bildet die Datenbank FastObjects .NET von Poet
die Grundlage.
97
7
7.1
Implementierung mit objektrelationaler Datenbank
Einleitung
Während in der relationalen Datenbank eine strikte Trennung zwischen Daten und
Semantik besteht, soll diese Trennung durch Hinzufügen weiterer Anwendungslogik
in die Datenbank verringert werden. Durch die Bildung von komplexen und geschachtelten Datentypen können beliebige Strukturen gebildet werden. Zusätzlich
kann Verhalten an die Tupel gebunden werden, wodurch Tupel zu Objekten im objektorientierten Sinne werden. Das Ziel des objektrelationalen Datenmodells ist es,
ein Klassenmodell eins-zu-eins auf das Datenmodell abbilden zu können. Im Idealfall
existiert die komplette (objektorientierte) Anwendungslogik in der objektrelationalen Datenbank und nur ein einfaches grafisches Benutzerinterface wird benötigt,
um Funktionalitäten auszuführen und Daten, die gekapselt sind, abzufragen und zu
manipulieren. Dabei sollen die Vorteile einer relationalen Datenbank nicht verloren
gehen.
Bei der Entwicklung einer objektrelationalen Datenbank gibt es prinzipiell zwei
Herangehensweisen. Die erste Möglichkeit ist die Entwicklung eines objektrelationalen Datenmodells auf der Basis eines Klassenmodells. Dieses Thema wird in Kapitel
7.5 kurz angesprochen. Der andere Weg, der hier detaillierter vorgestellt wird, besteht darin, das relationale Datenmodell schrittweise um objektrelationale Konzepte
zu erweitern.
Als Vergleichsgrundlage dient das relationale Datenmodell in Abbildung 55 aus
Kapitel 6.7.2 mit den Vergleichskriterien aus Kapitel 6.8.3. Wie bereits erwähnt
wurde, ist der SQL-99 Standard, der die objektrelationalen Konzepte enthält, eine
Erweiterung des SQL-92 Standards, wodurch sich schon erahnen lässt, dass dieser
ziemlich umgangreich ist. Durch die Erweiterung von SQL-92 besteht in der objektrelationalen Datenbank die Möglichkeit relationale und objektrelationale Konzepte
beliebig miteinander zu kombinieren.
Die SQL-Dialekte der real existierenden Datenbanksysteme unterstützen die SQL99 Norm nur in höchst unvollständiger Form und sind zudem sehr heterogen (vgl.
[Luf 02]). Eine konkrete Implementierung mit einer objektrelationalen Datenbank
konnte nicht vorgenommen werden, da die zur Verfügung stehende Informix Datenbank 3.31 einige grundlegende Konzepte nicht unterstützt. Aus diesem Grund wird
im Folgenden von einer SQL-99 konformen Datenbank ausgegangen. Größtenteils
basieren die folgenden Kapitel auf den Darstellungen von [Tür 03].
Ausgehend von Kapitel 6 werden in diesem Kapitel die Erweiterungen für die
Datendefinition (siehe Kapitel 7.2) und die daraus resultierenden Erweiterungen für
98
die Datenmanipulation und die Datenabfrage untersucht (siehe Kapitel 7.3).
7.2
7.2.1
Erweiterte Datendefinition
Einleitung
Durch Erweiterungen des relationalen Datenmodells um Konzepte wie komplexe Datentypen, Methoden, Objektidentitäten, Kapselung und Vererbung sollen die Vorteile einer relationalen Datenbank mit denen der Objektorientierung kombiniert werden. Im Folgenden werden die objektrelationalen Konzepte von SQL-99 vorgestellt,
die dies ermöglichen. Basierend auf dem Datenmodell in Abbildung 55 aus Kapitel
6.7.2 werden jeweils Beispiele vorgestellt, die zeigen, wie das relationale Datenmodell
erweitert werden kann.
Benutzerdefinierte Typen und strukturierte Typen bilden die Grundlage zur Definition von komplexen und geschachtelten Typen. Dabei werden die benutzerdefinierte Typen in unbenannte und benannte unterteilt.
Unbenannte Typen sind Tupeltypen, Arrays und Refererenztypen. Im Gegensatz
dazu gibt es die Distinct Datentypen (vgl [Tür 03, S. 50 f.]), die, ähnlich zu dem
Konzept der Domänen (vgl. Kapitel 6.2.1), neue Typen definieren. Im Gegensatz zu
den Domänen sind diese streng typisiert. Benutzerdefinierte Datentypen können als
Attribute in Tabellen definiert werden und geben somit der Tabelle mehr Struktur.
Strukturierte Typen sind klassenähnliche Typen, die durch Definition einer Objektidentität zu Klassen werden. Von diesen können Instanzen gebildet werden, die
ähnlich den Objekten im objektorientierten Sinne sind. Die Klassen bieten das Konzept der Vererbung an und ermöglichen dynamisches Binden, wie in Kapitel 7.2.4
beschrieben wird.
Verwaltet werden strukturierte Typen in typisierten Tabellen. Typisierte Tabellen bilden sozusagen einen Container (vgl. [Luf 99]) für Objekte bzw. strukturierte
Typen. Durch die Definition von Referenzen in den strukturierten Typen werden die
in der relationalen Datenbank verwendeten Verbunde ersetzt, d. h., auf die abhängigen Tabellen wird durch eine aufgelöste Referenz zugegriffen (vgl. 6.4.1).
Eine Erweiterung der Sichten des relationalen Datenmodells (vgl. 6.2.7) sind
die typisierten Sichten. Durch diese können Sichten auf strukturierte Typen bzw.
Objekte definiert werden.
7.2.2
Distinct-Typen
Ähnlich zu dem Prinzip der Domänen definieren Distinct-Typen neue Datentypen.
Für Distinct-Typen kann keine Einschränkung definiert werden. Sie sind lediglich
99
eine Kopie des angegebenen Basistyps. Der entscheidene Vorteil ist, dass diese streng
typisiert sind. Das Konzept der Vererbung bieten Distinct-Typen nicht.
7.2.3
Unbenannte Typkonstruktoren
Definiert wird ein unbenannter Typ durch einen Typkonstruktor. Im Folgenden werden die drei in 7.2.1 vorgestellten unbenannten Typkonstruktoren vorgestellt.
Tupeltypkonstruktor
Durch Tupeltypkonstruktoren lassen sich Tupel bilden, die als Attribute in Tabellen verwendet werden können. Logisch zusammengehörige Attribute können somit
zusammengefasst werden und geben dem relationalen Datenmodell mehr Struktur.
Wie in Abbildung 64 zu sehen ist, können der Name und die Benutzerrechte
eines Mitarbeiters jeweils als Tupel definiert werden. Ein Mitarbeiter besitzt dann
nur noch die zwei Attribute: Name und Role. Die Gruppierung von Attributen ist,
vor allem wenn es sich um Tabellen mit sehr vielen Attributen handelt, ein gutes
Konzept um verständlichere Modelle zu erzeugen. Zugegriffen wird auf die Elemente
eines Tupeltyps über die Punktnotation, wie in Abbildung 64,(5) gezeigt.
(1)
(2)
(3)
(4)
...
(5)
...
CREATE TABLE Employee (
Name ROW( Firstname VARCHAR(50), Lastname VARCHAR(50) ),
Role ROW( Admin BOOLEAN, DepartLeader BOOLEAN, ... )
)
SELECT ... FROM Employee WHERE ... Employee.Name.Firstname
Abbildung 64: Beispiel für Tupeltypkonstruktor
Arraytypkonstruktor
Ein weiteres Konzept der unbenannten Typkonstruktoren ist der Arraytypkonstruktor. Für die Typen, die in einem Array enthalten sind, sind alle Elementtypen
zulässig. Komplexe Datentypen und geschachtelte Arrays (vgl. [Tür 03, S. 47]) sind
nicht möglich, d. h., SQL-99 ist nicht vollständig orthogonal, so wie es in [Atk+ 95]
(vgl. 6.8.3) gefordert wurde.
Für den Datenbankentwurf bedeutet dies, dass in der Entwicklung immer Ausnahmeregeln und Sonderfälle beachtet werden müssen und die Möglichkeiten des
Datenbankentwurfs eingeschränkt sind. Problematisch ist dies vor allen dann, wenn
ein Klassenmodell in einer objektrelationalen Datenbank abgebildet werden soll (sie-
100
he Kapitel 7.5).
CREATE TABLE Employee (
...
Accounts VARCHAR(15) ARRAY[20]
...
)
Abbildung 65: Beispiel für Arraytypkonstruktor
Die Accounts der Mitarbeiter aus der Zeiterfassung sind ein gutes Beispiel für die
Verwendung von Arrays (vgl. Abbildung 65). Um der ersten Normalform zu entsprechen, wurden die Accounts in eine separate Tabelle EmployeeAccount ausgelagert
und über die Fremdschlüsselverbindung EmployeeID mit der Tabelle Employee verbunden (vgl. Abbildung 55 aus Kapitel 6.7.2). Da diese Tabelle nur ein elementares
Attribut, nämlich Windowsname enthält, kann diese als ein Array in Employee verwendet werden. Wie in Abbildung 65 zu sehen ist, besteht darüber hinaus die Möglichkeit, die Menge der Elemente in dem Array zu beschränken. Diese Beschränkung
wäre in der relationalen Datenbank nur durch zusätzliche Integritätsbedingungen
möglich (vgl. 6.2.5).
Die Meinungen, ob es sich bei den Array und Tupeltypen um eine Verletzung
der ersten Normalform handelt, gehen dabei auseinander (vgl. [Eis+ 99, S. 2] und
als Beispiel [Saa 03, S. 533]). Prinzipiell bilden diese Konstrukte nur eine andere
Form der Darstellung. Über einen Unnest-Operator lässt sich ein Array wieder in
eine Tabelle transformieren, wie in Abbildung 66 dargestellt ist.
Abfrage auf der Tabelle von Abbildung 55:
SELECT * FROM Employee e, EmployeeAccount a
WHERE e.EmployeeID=a.EmployeeID
Abfrage auf der Tabelle von Abbildung 65:
SELECT * FROM Employee UNNEST(Accounts)
Abbildung 66: Beispiel für eine SQL-Anfrage auf einem Array
Referenztypkonstruktor
Während in einer relationalen Datenbank die Abhängigkeiten der Tabellen untereinander über Schlüsselverbindungen definiert werden, besteht bei einer objektrelationalen Datenbank die Möglichkeit, diese über Referenzen zu verbinden. Referenzen
sind, anders als Fremdschlüsselverbindungen, streng typisiert und können nur auf
101
typisierte Tabellen angewendet werden. Das Konzept der typisierten Tabellen wird
in Kapitel 7.2.4 noch detaillierter beschrieben.
Ein Beispiel für eine Referenz ist die Verbindung von Employee und Project
(vgl. Abbildung 55 aus Kapitel 6.7.2). Während in dem relationalen Datenmodell
die Projektleiter (ProjectLeader ) der Projekte über einen Verbund aus Employee und
Project ermittelt werden müssen, können diese über Referenzen direkt angesprochen
werden. Eine Anfrage aller Projekte mit ihren Projektleitern, die Bedingung X erfüllen, könnte dann über eine Referenzauflösung realisiert werden, wie im Beispiel von
Abbildung 67 dargestellt. Referenzen haben zum einen den Vorteil, dass dadurch
Queries verständlicher formuliert werden können, zum anderen sind Zugriffe über
Referenzen sehr viel effizienter, als aufwendige Verbunde über mehrere Tabellen.
Definition in Project:
COLUMN ProjectLeaderID REF(Employee) ..
Alter Query:
SELECT e.Lastname as ProjectLeaderLastname
FROM Project p, Employee e
WHERE p.ProjectLeaderID = e.EmployeeID AND X
Neuer Query:
SELECT ProjectLeaderID->EmployeeID FROM Project WHERE X
Abbildung 67: Beispiel für einen Referenztypkonstruktor
Dieses Beispiel ist noch relativ einfach. Bei aufwendigeren Anfragen, die sich über
mehrere Tabellen erstrecken, sieht man den Nutzen. Eine Anfrage, die beschreibt,
in wie vielen Projekten der Projektgruppe X ein Mitarbeiter Y bereits Projektleiter
war, würde dann wie in Abbildung 68 aussehen.
SELECT COUNT(*) FROM Project p
WHERE p->ProjectGroupID->Name=X
AND p->ProjectLeaderID->Lastname=Y
Abbildung 68: Beispiel für die Vorteile von Zugriffen über Referenzen
Die Beispiele bildeten jedoch nur 1:1-Beziehungen ab. Zur Realisierung einer 1:nBeziehung muss ein Array der Größe n von Referenzen gebildet werden. Abbildung
69 stellt die 1:n-Beziehung zwischen Mitarbeitern und ihren Verträgen dar.
Statt einer ungerichteten m:n-Beziehung muss der Umweg über zwei gerichtete
1:n-Beziehungen gegangen werden (vgl. [Lau 01]).
102
CREATE TYPE EmployeeType
AS (... contract REF(ContractType) Array[n] ...);
Abbildung 69: Beispiel für 1:n-Relation
7.2.4
Strukturierte Typen
Strukturierte Typen sind ebenfalls benutzerdefinierte Typen mit einigen Erweiterungen (vgl. Abbildung 70). Sie entsprechen in etwa dem Konzept der Klasse und enthalten Attribute und Methoden. Durch Vererbung ermöglichen sie das Konzept der
Substituierbarkeit. Jedes Attribut wird vom System automatisch gekapselt. Im Folgenden wird beschrieben, wie diese Konzepte realisiert wurden und welche Schwierigkeiten sich dabei ergeben.
komplexe Datentypen: Strukturierte Typen können mehr als ein Attribut definieren und jedes Attribut kann wiederum ein beliebiger Datentyp sein.
Verhalten: Das Verhalten eines strukturierten Typs kann durch Methoden, Prozeduren und Funktionen realisiert werden.
Kapselung: Für jedes Attribut wird vom System eine Observer- und eine Mutatormethode generiert (get- und set-Methoden).
Vererbung: Jeder strukturierte Typ kann spezialisiert und generalisiert werden.
Abbildung 70: Merkmale eines strukturierten Typs (basiert auf [Eis+ 99])
Wie in Abbildung 71 dargestellt, besteht ein strukturierter Typ aus einem Typnamen, Attributen und Methodendeklarationen. Damit ein strukturierter Typ zu
einem Objekt im objektorientierten Sinne wird, muss eine Objektidentität definiert
werden. Es besteht zwar die Möglichkeit, diese abhängig von den Attributen oder
noch schlimmer benutzerdefiniert zu definieren, da diese Einstellungen aber dem
Grundgedanken (vgl. [Tür 03, S. 57 f.]) einer unabhängigen und systemverwalteten Objektidentität widersprechen würden, sollten diese durch den Ausdruck ”REF
IS SYSTEM GENERATED” als vom System generiert gesetzt werden (vgl. auch
Kapitel 6.8.3).
Ein strukturierter Typ kann von einem anderen strukturierten Typen erben und
zusätzliche Attribute und Methoden definieren und Methoden überschreiben. Dadurch wird Substituierbarkeit von strukturierten Typen möglich, d. h., überall, wo
ein bestimmter Typ erwartet wird, kann auch ein abgeleiteter Typ eingesetzt werden.
Attribute
103
CREATE TYPE <Typname>
[UNDER <Suptertypname>]
AS
( <Attribute>)
[[NOT] INSTANTIABLE]
[[NOT] FINAL]
[<OID-Typspezifikation>]
[<Methodendeklaration>]
Abbildung 71: Aufbau eines strukturierten Typs
Die Definition der Attribute erfolgt in einer ähnlichen Form wie die Definition
der Attribute in einer Tabelle. Jedes Attribut besitzt einen Namen, einen Datentyp
und optional einen Defaultwert.
Für jedes Attribut werden vom System zwei Methoden erzeugt, welche die Attribute durch so genannte Observer - und Mutator -Methoden kapseln. Das Lesen
bzw. Schreiben eines Attributs wird zwar wie ein direkter Attributszugriff durchgeführt, führt aber intern die entsprechende Methode aus. Die Methoden können
überschrieben werden, wobei für jedes Attribut genau eine Observer - und eine Mutator -Methode vorhanden ist. Verschiedene Sichten auf ein Attribut sind damit nicht
möglich. Dadurch dass die Observer - und die Mutator -Methoden den gleichen Namen wie ihre Attribute besitzen, kann eigentlich nicht wirklich von Kapslung gesprochen werden, da Änderungen an einem Attribut die Schnittstelle nach außen
verändern würden (vgl. mit dem Punkt Kapselung aus Kapitel 6.8.3). Die einzige
Form von Kapselung, die möglich ist, ist, die Bedingungen in einer überschriebenen
Mutator- oder Observermethode zu definieren.
Methoden
Die Methodendeklaration erfolgt direkt in der Definition eines strukturierten
Typs. Die dazugehörige Methodenimplementierung muss separat erzeugt werden und
an den entsprechenden strukturierten Typ gebunden werden. Es gibt drei Arten von
Methoden, die jeweils mit einem entsprechenden Schlüsselwort gekennzeichnet werden müssen: Instanzmethoden, Konstruktormethoden und statische Methoden. Die
Instanz- und die Konstruktormethoden besitzen einen impliziten Self-Parameter (die
Objektidentität oid ). Neben dem Überladen (overloading) von Methoden besteht
die Möglichkeit, Methoden zu überschreiben. Methoden, die überschrieben wurden,
müssen, genauso wie in C#, durch das Schlüsselwort OVERRIDING gekennzeichnet werden. Substituierbarkeit und das Überschreiben von Methoden ermöglichen
dynamisches Binden. Neben den Aufrufen der Methoden in anderen Methoden können diese auch direkt in den SQL-Queries verwendet werden, um zum Beispiel in
einer Where-Klausel eine Prüfung vorzunehmen. Im SQL-99 werden dabei einige
104
Einschränkungen definiert, wie in Kapitel 7.3 noch beschrieben wird. Diese verhindern unerwünschte Seiteneffekte.
Zu jedem instanziierbaren strukturierten Typ wird ein Defaultkonstruktor angelegt, analog zu dem Defaultkonstruktor in der Objektorientierung. Der Konstruktor
liefert eine Instanz des jeweiligen strukturierten Typs zurück. Außerdem besteht die
Möglichkeit, weitere Konstruktoren mit Parametern zu definieren.
Abstrakte und nicht weiter vererbbare Typen
Durch den Zusatz Not Instantiable kann ein strukturierter Typ als abstrakt definiert werden, d. h., von diesem können keine Instanzen gebildet werden. Allerdings
können keine abstrakten Methoden definiert werden.
Der Zusatz FINAL gibt an, dass von diesem Typ nicht abgeleitet werden darf,
und ist vergleichbar mit dem sealed in C#.
Typprüfung
Über das Konstrukt IS OF können Objekte auf ihre Typen hin überprüft werden, wobei mit dem Zusatz ONLY angegeben werden kann, ob genau dieser Typ
(ohne seine Subtypen) oder ein Typ inklusive seiner Subtypen überprüft wird. Das
Casten eines strukturierten Typs auf einen Subtypen ist durch TREAT (<Supertypname>) AS (<Subtypname>) ebenfalls möglich.
Soweit ist (fast) alles so, wie man es von einer objektorientierten Sprache erwartet. Einige Konzepte, wie beispielsweise Sichtbarkeiten18 oder Interfaces, werden
nicht unterstützt. Des Weiteren besteht keine Möglichkeit, Typen in Komponenten
oder Packages und damit das Datenmodell in mehrere Teilmodelle zu unterteilen.
7.2.5
Typisierte Tabellen
Eine typisierte Tabelle basiert auf einem strukturierten Typ und enthält eine Menge
von strukturierten Typen. Gemäß [Atk+ 95] wird in einer objektrelationalen Datenbank zwischen (strukturierten) Typen und Tabellen (Klassen) unterschieden. In
Abbildung 72 ist der Definitionsaufbau einer typisierten Tabelle vereinfacht dargestellt.
Typisierte Tabellen können, genau wie strukturierte Typen, vererbt werden. Eine
abgeleitete typisierte Tabelle erbt alle Attribute und Methoden und kann Methoden überschreiben. Die Methoden und Attribute werden durch den entsprechenden
strukturierten Typen vorgegeben. Des Weiteren können Attribute und Methoden
18
public, private, protected
105
CREATE TABLE <Tabellenname>
OF <Typname>
[UNDER <Suptabellenname>]
Abbildung 72: Vereinfachter Definitionsaufbau einer typisierten Tabelle
hinzugefügt werden, wobei sich dabei ein Problem ergibt (vgl. auch [Tür 03, S. 7579]).
Bei der Anfrage auf einer typisierten Tabelle wird zwischen flacher und tiefer Extension unterschieden. Eine tiefe Extension beinhaltet alle Tupel einer Tabelle und
alle Tupel der typisierten Subtabelle dieser Tabelle, während die flache Extension
nur die Tupel der Supertabelle enthält. Bildet man nun eine tiefe Extension auf einer
typisierten Tabelle, die mehrere Subtabellen enthält, so besteht keine Möglichkeit
(auch durch explizites Casten nicht), auf die hinzugefügten Attribute oder Methoden
der Subtabellen zuzugreifen. Das Ergebnis einer tiefen - genauso wie einer flachen Extension ist wiederum nur eine Tabelle, die Spalten und Zeilen enthält. Neu hinzugefügte Spalten der Subtypen erscheinen in der tiefen Extension nicht (siehe auch
[Tür 03, S. 76 bis 79]).
An dem Beispiel von Abbildung 63 auf Seite 94 kann man sehen, dass durch eine
flache Extension auf Employee die Menge aller Mitarbeiter zurückgegeben wird, die
keine Verträge besitzen. Die tiefe Extension auf Employee liefert die Menge aller
Mitarbeiter zurück.
Da keine abstrakten Methoden definiert werden können, ist Vererbung nur in sehr
eingeschränktem Maß möglich. Es besteht lediglich die Möglichkeit, anstelle einer
abstrakten Methode eine Methode zu definieren, die eine Exception zurückliefert.
Das Problem dabei ist, dass typisierte Tabellen prinzipiell nur Tabellen mit einer
speziellen Spalte für die Objektidentität sind. Die Attribute des entsprechenden
strukturierten Typs werden in Attribute einer Tabelle umgewandelt. Dadurch sind
direkte Manipulationen an den Attributen möglich, ohne dass auf die Mutator- und
Observer-Methoden zugegriffen wird.
7.2.6
Typisierte Sichten
Ein weiteres Konzept sind die typisierten Sichten. Eine typisierte Sicht ermöglicht
eine Sicht auf ein Objekt, d. h., sie basiert auf einem strukturierten Typen und definiert auf diesen eine SQL-Anfrage. Im Gegensatz zu den Tupelsichten haben die
Objekte einer typisierten Sicht eine Objektidentität und auf ihnen können Methoden
aufgerufen werden. Außerdem kann angegeben werden, ob es sich bei der entsprechenden Anfrage um eine flache oder eine tiefe Extension handelt.
106
Typisierte Sichten können vererbt werden, wobei der strukturierte Typ der Subsicht direkt oder indirekt von dem strukturierten Typ der basierenden typisierten
Sicht abgeleitet werden muss.
Abbildung 73: Beispiel für eine typisierte Sicht
Wie in Abbildung 73 zu sehen ist, ist ein Mitarbeiter mit Vertrag (EmployeeWithContract) eine Erweiterung eines Mitarbeiters (Employee) (vgl. auch Kapitel
6.8.2). Die typisierten Sichten beschränken sich darauf, dass nur Mitarbeiter zurückgegeben werden, die im Moment aktiv sind. Wie schon in Kapitel 6.8.2 beschrieben
wurde, besitzen Mitarbeiter mit und ohne Vertrag jeweils unterschiedliche Implementierungen für die Abfrage und das Setzen des aktiven Status, wobei in diesem
Beispiel nur die Abfrage (Active()) berücksichtigt wird.
Eine tiefe Extension auf der typisierten Sicht AktiveMitarbeiter liefert alle Mitarbeiter zurück, die im Moment aktiv sind. Dies beinhaltet auch die Mitarbeiter mit
Vertrag. Intern wird die SQL-Anfrage für die typisierte Sicht AktiveMitarbeiter und
alle darin enthaltenden Subsichten, in diesem Fall nur AktiveMitarbeiterMitVertrag,
ausgeführt (vgl. [Tür 03, S. 79-84]). Eine flache Extension auf der typisierten Sicht
AktiveMitarbeiter liefert nur die Mitarbeiter ohne Vertrag zurück, die im Moment
aktiv sind.
7.3
Erweiterte Datenabfragen und -manipulation
Entsprechend zu der erweiterten Datendefinition wurde in SQL-99 auch die Datenselektion angepasst. Die Verwendung von Referenzen führt dazu, dass über die
Abhängigkeiten der Tabellen navigiert werden kann, wie schon gezeigt wurde. Die
Anfragen lassen sich somit übersichtlicher formulieren und sind leistungsfähiger, da
keine Verbunde mehr gebildet werden müssen.
107
Die Referenztypen enthalten intern die Objektidentität des referenzierten Objekts. Über einen Pfeiloperator (vgl. mit Abbildung 67 und 68 auf Seite 102) können
Referenzen aufgelöst werden und liefern somit das referenzierte Objekt zurück. Methoden werden auf ihren Referenzwerten ausgeführt und können in den SQL-Querys
(fast) beliebig verwendet werden. Beispielsweise könnte eine SQL-Anfrage in ihrer
Where-Klausel einen Methodenaufruf enthalten, wie schon in Kapitel 7.2.6 beschrieben wurde.
Dadurch dass objektrelationale und relationale Techniken beliebig kombiniert
werden können, sind somit beliebig komplizierte Anfragen möglich. Bisher wurde
immer von einer SQL-99 konformen Datenbank ausgegangen. Da die Realität aber
ganz anders aussieht, ist z. Z. ein Mischen dieser beiden Techniken nötig. Beispielsweise bietet die mir zur Verfügung stehende Informix Datenbank keine Referenzen
an. Es hätten sich zwar beliebig komplexe Datentypen definieren lassen, aber entsprechend kompliziert wären auch die Anfragen geworden.
Zur Vermeidung von unerwünschten Seiteneffekten wurden in SQL-99 einige Einschränkungen definiert. Beispielsweise dürfen in einer Where-Klausel keine Methoden oder sonstigen benutzerdefinierten Routinen aufgerufen werden, die Änderungen an den Daten vornehmen (vgl. [Tür 03, S. 256 f.]). Die Änderungen durch ein
Update-Statement werden auf eine Tabelle beschränkt, d. h., die Daten einer aufgelösten Referenz dürfen nicht verändert werden.
Die Nebenläufigkeitsprobleme, wie in Kapitel 6.3 beschrieben wurde, sind in einer
objektrelationalen Datenbank die gleichen.
7.4
Bewertung nach Datenbankmanifesto
Konzeptionell bietet SQL-99 interessante Konzepte um Objektorientierung in der
relationalen Datenbank zu ermöglichen. Im Folgenden wird das Konzept der objektrelationalen Datenbank anhand der in Kapitel 6.8.3 geforderten Bedingungen von
[Atk+ 95] untersucht.
7.4.1
Komplexe Datentypen
Wie in Kapitel 7.2 beschrieben wurde, bietet SQL-99 verschiedene Möglichkeiten, um
komplexe Datentypen zu definieren. Distinct-, Tupel-, Arraytypen ermöglichen es,
mehr Struktur in das Datenmodell zu bringen. Mit den strukturierten Typen lassen
sich Typen bilden, die, ähnlich zu einer Klasse, mehrere Typen zu einem Typen
zusammenfassen. Allerdings sind die Konstruktoren nicht vollständig orthogonal, so
wie gefordert wurde.
108
7.4.2
Objektidentität
Durch das Konzept der strukturierten Typen und die vom System generierten Objektidentitäten ist eine Unterscheidung von gleichen und denselben Objekten möglich. Allerdings muss diese Eigenschaft explizit definiert werden. Es besteht auch die
Möglichkeit, zustandsabhängige oder selbst definierte Objektidentitäten zu definieren, was aber der Idee einer Objektidentität widerspricht.
7.4.3
Kapselung
Die Anforderung nach einer sauberen Trennung zwischen Schnittstelle und Implementierung ist nicht gegeben, da keine Sichtbarkeiten definiert werden können und
alle strukturierten Typen und Methoden prinzipiell public sind. Die Kapselung der
Attribute ist auch nur in einem sehr eingeschränkten Maß gegeben, da für jedes
Attribut genau eine Mutator - und eine Observer -Methode definiert wird. Verschiedene Sichten eines Attributs sind damit nicht möglich. Dadurch dass die Mutatorund die Observermethode den gleichen Namen wie ihre Attribute haben, würden
Änderungen nach außen sichtbar. Die Mutator - und Observer -Methoden sind aber
ein geeignetes Mittel um Konsistenzprüfungen vorzunehmen, d. h. eine unzulässige
Zustandsübergabe abzufangen.
7.4.4
Typen- und Klassenhierarchien
Die Unterteilung von Klasen (typisierte Tabellen) und Typen (strukturierte Typen)
existiert so, wie es auch gefordert wurde. Auf einer strukturierten Tabelle lassen
sich, wie auch auf einer einfachen Tabelle, beliebige Operationen für eine Menge von
Objekten ausführen. Die geforderte Trennung zwischen Schnittstelle und Implementierung eines Typs ist nicht gegeben (vgl. mit Kapselung 7.4.3).
7.4.5
Vererbung
In einem eingeschränkten Maß ist auch Vererbung möglich. Die Definition von abstrakten Methoden ist nicht möglich. Zusätzlich definierte Attribute oder Methoden eines strukturierten abgeleiteten Typen können bei einer tiefen Extension auf
den Basistypen auch durch explizites Casten nicht verwendet werden (siehe Kapitel
7.2.5). Ein weiteres Problem ist, dass strukturierte Tabellen nur strukturierte Typen des gleichen Typs beinhalten dürfen. Abgeleitete Typen müssen in abgeleiteten
Tabellen abgelegt werden (s. Kapitel 7.5).
7.4.6
Override, Overload und spätes Binden
Overloading existiert sowohl für Methoden als auch für Funktionen und Prozeduren. Dynamisches Binden, wie in Kapitel 7.2.6 an einem Beispiel gezeigt wurde,
ermöglicht es, Methoden zur Laufzeit zu ermitteln.
109
7.4.7
Sprach- und Berechnungsvollständigkeit
Die Forderung nach Sprach- und Berechnungsvollständigkeit ist bereits durch die
in Kapitel 6.2.6 beschriebenen benutzerdefinierten Routinen gegeben. In den Methoden können dieselben Funktionalitäten wie in den benutzerdefinierten Routinen
verwendet werden, womit sich alle berechenbaren Operationen ausführen lassen.
7.4.8
Erweiterbarkeit von Typen
Wie schon in dem Punkt Kapselung beschrieben wurde, können (fast) beliebige
Typen gebildet und verwendet werden. Das Typsystem von SQL-99 macht dabei
keine Unterscheidung zwischen benutzerdefinierten und vorgegebenen Typen.
7.5
Klassenmodell in objektrelationales Datenmodell transformieren
Basierend auf der Vorgehensweise von [Fin 02, S. 63-68] wird in diesem Kapitel ein
Ansatz für eine Transformation von Klassenmodell auf objektrelationales Modell
vorgestellt. Eine entsprechende Anwendung mit einer identischen Klassenstruktur
wird aber auch in einem objektrelationalen Datenmodell immer nötig sein, da in
der objektrelationalen Datenbank kein grafisches Benutzerinterface oder irgendeine
andere Schnittstelle nach außen implementiert werden kann.
Datentypen nachbilden: Zunächst müssen die benötigten einfachen Datentypen
im objektrelationalen Datenmodell angelegt werden, sofern sie in der Form
noch nicht existieren.
Klassen werden zu strukturierten Typen: Klassen mit ihren Attributen werden zu strukturierten Typen mit einer vom System generierten Objektidentität. Diejenigen Attribute, die auf eine weitere Klasse verweisen, müssen als Referenzen abgebildet werden. 1:n-Beziehungen werden als Array von Referenzen
modelliert und m:n-Beziehungen werden durch zwei Beziehungen dargestellt.
Vererbung nachbilden: Die Vererbungsbeziehungen werden in strukturierten
Typen nachgebildet. Dabei sollte zu jedem strukturierten Typ eine entsprechende strukturierte Tabelle angelegt werden. Eine strukturierte Tabelle kann
nur Typen des genau gleichen Typs enthalten. Subtypen in eine strukturierte
Tabelle einzufügen geht nicht (vgl. [Fin 02, S. 66]). Diese müssen dann in die
entsprechende abgeleitete Tabelle (also die Tabelle des Subtypen) eingeführt
werden.
7.6
Zusammenfassung
Wie an den Punkten von Abschnitt 7.4 gezeigt wurde, ließen sich viele Anwendungen komplett in eine objektrelationale Datenbank auslagern. Das große Problem
110
ist die benötigte Abwärtskompatibilität zu SQL-92 und die damit verbundene fehlende Kapselung. Eine größere Entwicklung mit mehreren Entwicklern würde eine
erhöhte Disziplin der Entwickler erfordern, da vereinbarte Schnittstellen nicht in der
Datenbank realisiert werden könnten. Die Entwicklung eines Frameworks in einer
objektrelationalen Datenbank wäre beispielsweise durch die fehlenden abstrakten
Methoden und die fehlenden Sichtbarkeiten nicht in der Form möglich, wie in einer
objektorientierten Programmiersprache.
Das eigentliche Problem ist aber ganz anderer Art. In den real existierenden
objektrelationalen Datenbanken werden immer nur einige der Konzepte realisiert
und es ist erforderlich, dass die relationalen mit den objektrelationalen Konzepten
gemischt werden. Dadurch wird die Entwicklung sehr viel aufwendiger als bei einer
Trennung von relationaler Datenbank und Anwendung.
111
8
8.1
8.1.1
Vergleich: relationale und objektrelationale Datenbank
Relationale Datenbank
Modellierungsmöglichkeiten und Normalisierung
Ein großes Problem beim Entwurf war die Trennung zwischen Datenmodell und
Klassenmodell. Erschwerend kam noch hinzu, dass es zwei Arten von Klassenmodellen gab: das informative Klassenmodell aus dem Requirements Engineering (vgl.
Abbildung 8 auf Seite 28 und das Klassenmodell des Entwurfs der persistenten Objekte (vgl. Abbildung 26 auf Seite 51).
Um die Probleme der eingeschränkten Modellierungsmöglichkeiten zu verringern,
bildete das Datenmodell die Basis für den Entwurf und das Klassenmodell der Analyse diente nur als Informationsgrundlage.
Bei der Modellierung des Datenmodells wurden bewusst einige Normalisierungsschritte nicht vorgenommen, da diese das Datenmodell unübersichtlich gemacht und
die Tabellen nicht mehr die Entitäten der Realität dargestellt hätten. Ein Beispiel ist
das Attribut active in der Tabelle Employee (vgl. Abbildung 55 auf Seite 85), welches
für Vertragsmitarbeiter, d. h. Mitarbeiter, die eine Verbindung zu EmployeeContract
besitzen, keine Bedeutung hat. Da der Unterschied zwischen Vertragsmitarbeitern
und Mitarbeitern ohne Vertrag nicht allzu groß war, stellte diese ”Schwäche” kein
großes Problem dar.
In dem Beispiel von Abbildung 74 hingegen ist dies etwas komplizierter. Die links
dargestellten Klassen lassen sich auf zwei Arten abbilden.
Die erste Möglichkeit enthält alle Attribute, die möglich sind, d. h., in jedem
Datensatz sind Daten vorhanden, die keine Bedeutung haben, so wie beispielsweise
das Attribut active in der Tabelle Employee (vgl. Abbildung 55 auf Seite 85).
Die zweite Möglichkeit besteht darin, die Klassen direkt als Tabellen abzubilden
und die Vererbung durch Schlüsselverbindungen zu verbinden. Der Nachteil dieser
Variante ist, dass für jede Anfrage an B oder C jeweils ein Verbund mit der Tabelle
A durchgeführt werden muss und die ursprüngliche Modellierungsform nicht mehr
ersichtlich ist.
Ein weiteres Problem, was sich aus der Trennung von Datenmodell und Applikation über die SQL- Schnittstelle ergibt, ist, dass die SQL-Queries erst zur Laufzeit
überprüft werden können, da dies nur ein einfacher String ist. Ein vorheriges Überprüfen, ob beispielsweise Tabellen oder Attribute der Tabelle existieren, ist nicht
112
Abbildung 74: Zwei Möglichkeiten für Vererbung im ER-Modell
möglich. Dies ist vor allem bei Änderungen sehr aufwendig, da der entsprechende
Programmteil, der den geänderten Query enthält, jeweils durchlaufen werden muss.
8.1.2
Definition von Primärschlüsseln
In Kapitel 6.7.5 wurde bereits das Problem mit zusammengesetzten Primärschlüsseln beschrieben.
Die Definition von technischen Schlüsseln, die vom System erzeugt werden, aus
einem Attribut bestehen, welches unabhängig von den Werten des Datensatzes ist,
und die Definition von nicht-identifizierenden Verbindungen stellte sich als sehr vorteilhaft heraus.
Die zweite Normalform musste nicht mehr betrachtet werden, da sie in diesem
Fall nicht mehr auftreten kann. Die einzige Überprüfung zur Vermeidung von Redundanzen war die Betrachtung der Abhängigkeiten der (Nichtschlüssel-)Attribute
untereinander. Ausgenommen waren dabei die Tabellen, welche m:n-Beziehungen
darstellten.
Die Entitäten können dann nur noch über ihre definierten Abhängigkeiten verbunden werden. Wie in Abbildung 60 auf Seite 91 zu sehen war, war es bei den
113
zusammengesetzten Primärschlüsseln auch möglich, Tabellen miteinander zu verbinden, die nicht direkt in Beziehung stehen, wie beispielsweise in Abbildung 60 Fachgruppen (ProjectTeam) und Projektgruppen (ProjectGroup). In diesem Fall kann
aber wiederum das Problem Phantom Read (vgl. Kapitel 6.3.3) auftreten, da das
Projekt hier nicht betrachtet wird und damit auch nicht gelockt werden kann.
8.1.3
Integritätsbedingungen
Integritätsbedingungen zwischen Entitäten werden durch Fremdschlüssel realisiert.
Für komplexere Bedingungen können Trigger verwendet werden. Trigger haben allerdings den Nachteil, dass sie nur auf Ereignisse in einer Tabelle reagieren können,
d. h., für eine komplexere Überprüfung müssten verschiedenste Trigger definiert werden, um eine Integritätsbedingung zu erfüllen.
Ein Beispiel ist die Überprüfung, die sicherstellt, dass Daten in den Mitarbeiterwochen nur geändert werden können, wenn diese noch nicht geschlossen sind (vgl.
mit dem Attribut finish in der Tabelle EmployeeWeek ist (vgl. Abbildung 55 auf
Seite 85). Für diese Überprüfung wären vier Trigger für die folgenden Tabellen nötig: EmployeeWeek, ProjectEmployee, TeamEmployee und ActivityEmployee.
Da diese das Datenmodell recht kompliziert machen und bei jeder Änderung
manuell mit geändert werden müssten, wurde auf die Verwendung von Triggern
verzichtet.
8.1.4
Abfragemöglichkeiten und Datenmanipulation
Bei der Formulierung der Abfragen müssen alle denkbaren Abhängigkeiten mit betrachtet werden, d. h., wenn beispielsweise eine Liste mit Projekten ermittelt werden
soll und noch nicht genau feststeht, ob die abhängigen Projektleiter wirklich benötigt
werden, so müssen diese in der Anfrage mit angeben werden. Die andere Möglichkeit ist, die geforderten Daten explizit bei Bedarf anzufordern, wobei hier sperrende
Transaktionen verwendet werden sollten.
Durch die Verwendung von Sichten können die Anfragen zwar erleichtert werden,
aber Sichten ”verstecken” die aufwendigen Anfragen nur. Beim Erzeugen, Ändern
oder Löschen von Datensätzen muss wieder auf die hinter den Sichten liegenden Tabellen zugegriffen werden.
Das Ändern, Löschen und Einfügen von Datensätzen ist pro Query nur auf eine
Tabelle beschränk, d. h. Operationen dieser Art, die sich über mehrere Tabellen
erstrecken, müssen in mehreren Queries formuliert werden.
114
8.1.5
Nebenläufigkeit und Performanz
Einer der großen Vorteile einer relationalen Datenbank ist die Performanz. Wie sich
aber herausgestellt hat, ist es sinnvoll, für jede Entität ein Attribut als Primärschlüssel zu definieren, der unabhängig vom Zustand der Datensätze ist und vom System
bzw. von der Datenbank erzeugt wird, d. h., die Tabellen können nur über ihre definierten Schlüsselverbindungen miteinander verbunden werden. Dadurch müssen bei
den Verbund-Operationen auch genau diese Verbindungen berücksichtigt werden,
wodurch aufwendige Verbunde über mehrere Tabellen nötig sind. Die Nebenläufigkeitsprobleme habe gezeigt, dass Phantom Read durchaus zu einem Problem führen
kann, was nur durch Serialisieren der Transaktionen gelöst werden kann. Inwieweit
die relationalen Datenbanken dann immer noch so leistungsstark sind, ist fraglich.
8.2
Verbesserungen durch eine objektrelationale Datenbank?
Bei einer Realisierung mit einem objektrelationalen Datenmodell kann das erstellte
Klassenmodell sowohl für die Anwendung als auch für die Datenbank verwendet werden, d. h., umständliche Umwandlungen oder von vornherein eingeschränkte Modellierungstechniken sind nicht mehr nötig. Die in Abbildung 74 dargestellten Klassen
ließen sich eins-zu-eins in einer objektrelationalen Datenbank abbilden.
Eine Businesslogik wird aber auch in einer objektrelationalen Datenbank immer
nötig sein, da keine Möglichkeiten für die Gestaltung einer grafischen Benutzeroberfläche oder eines anderen Interfaces gegeben sind. Der Zugriff erfolgt ebenfalls über
SQL, wobei eine Überprüfung auf syntaktische Korrektheit auch erst zur Laufzeit
ausgeführt werden kann.
Die Problematik mit den Primärschlüsseln ist in diesem Fall nicht gegeben, da
für jeden strukturierten Typen eine vom System generierte Objektidentität ermittelt
werden kann.
Die Verwendung von aufgelösten Referenzen führt dazu, dass Queries einfacher
formuliert werden können und verständlicher sind. Des Weiteren sind keine aufwendigen Verbundoperationen mehr nötig.
Durch die Definition von Methoden in den strukturierten Typen können Funktionalitäten, die sonst nur in der Businesslogik realisiert wurden, direkt in der Datenbank ausgeführt werden. Allerdings sind die Möglichkeiten nach SQL-99 im Vergleich
zu einer objektorientierten Programmiersprache eingeschränkter.
Die Transaktionsprobleme sind in einer objektrelationalen Datenbank aber immer noch die gleichen, wobei sich durch das komplexere Datenmodell mehr Anwendungssemantik in die Datenbank verlagern lässt und damit weniger Queries an die
115
Datenbank nötig sind.
8.3
Vergleich objektrelational zu relational zusammengefasst
relational
objektrelational
Flache Strukturen
Vererbung
Primärschlüssel
Objektidentität
Verbundoperationen
aufgelöste Referenzen
Trigger und benutzerdefinierte Routinen
Methoden
Sichten
Objektsichten (typisierte Sichten)
eingeschränkte Kapselung
Abbildung 75: Überblick relationale zu objektrelationaler Datenbank
Wie in Abbildung 75 zu sehen ist, bietet eine objektrelationale Datenbank im
Vergleich zu einer relationalen viele Vorteile. Leider ist dieser Ansatz nur Theorie,
wobei sich hierbei auch die Frage stellt, ob die Vorteile einer relationalen Datenbank
(vgl. Kapitel 6.8.1) in einem objektrelationalen Datenmodell immer noch gegeben
sind. Die Idee der objektrelationalen Erweiterung war, die Vorteile der Objektorientierung mit denen der relationalen Datenbank zu verbinden.
9
9.1
Zusammenfassung und Ausblick
Objektorientierte Datenbank
Einen völlig anderen Ansatz verfolgt die objektorientierte Datenbank. Sie bringt, im
Gegensatz zu einer objektrelationalen Datenbank, nicht die Anwendungssemantik in
die Datenbank, sondern die Persistenzeigenschaften in die Programmiersprache.
Das Datenmodell kann als Klassenmodell entworfen werden und über einen ”Zusatz” werden automatisch Persistenzeigenschaften realisiert. Eine Möglichkeit ist der
Attributemechanismus von .NET (.NET-Attribute). Dieser erlaubt es u. a., über Reflexion Objektinformationen zur Laufzeit zu bestimmen.
Die FastObjects Datenbank von Poet ist ein Beispiel für eine objektorientierte
Datenbank, die diesen Mechanismus verwendet. Genauso wie in einem relationalen
oder einem objektrelationalen Datenbankkonzept muss hierfür eine Transaktion geöffnet werden. In dieser Transaktion können Daten erzeugt, gelesen, geändert und
gelöscht werden. Beim Schließen der Transaktion werden die geänderten Daten automatisch auch in der Datenbank aktualisiert.
116
In Abbildung 76 ist ein Beispiel dargestellt für die Definition eines konkreten
persistenten Objekts aus der Zeiterfassung.
(1) [Persistent]
(2) public class CostCenterImpl : CostCenter {
(3) public CostCenterImpl(){}
(4) public override string Name{...}
(5) private string m OOName;
(6) }
(7) IObjectScope scope
(8) = FastObjects.Database.Get(<Datenbank>).GetObjectScope();
(9) scope.Transaction.Begin();
(10) foreach( CostCenterImpl p in scope.GetExtent( typeof(CostCenterImpl) ) )
(11)
// Irgendetwas mit p machen
(6) scope.Transaction.Commit();
Abbildung 76: Beispiel für eine Implementierung mit objektorientierter Datenbank
Sobald die ersten Objekte ermittelt wurden, kann auf die abhängigen Objekte
direkt zugegriffen werden (Persistence by Reachability). Diese Objekte müssen nicht
explizit aus der Datenbank ausgelesen werden. In der relationalen und der objektrelationalen Datenbank hätten dafür alle benötigten abhängigen Objekte bzw. Tupel
in dem Query mit ausgelesen werden müssen.
In dem Beispiel von Abbildung 76 kann beispielsweise das Attribute m OOName
(Zeile 5) über die Property Name geändert werden. Nach dem Commit ist diese Änderung dann persistenz, ohne dass explizite Queries an die Datenbank geschickt
werden, die diese Änderung vornehmen.
Um auf Objekte zugreifen zu können, wurde von der ODMG-Untergruppe OMG
der Standard OQL entwickelt, der, ähnlich zu SQL, eine Abfragesprache für eine
objektorientierte Datenbank definiert. Die Syntax ist dabei sehr ähnlich zu SQL-92.
Der Unterschied zu SQL ist, dass, die Anfragen auf einer Extension statt auf einer
Relation formuliert werden, d. h. auf einer Menge von Objekten. Im Gegensatz zu
SQL-99 liefert eine OQL-Anfrage ”echte” Objekte zurück. Abhängige Daten können
dabei genauso wie bei SQL-99 über Navigation angesprochen werden.
Anstelle von Events bietet die FastObjects .NET Datenbank Events an, an denen
sich Methoden registrieren können. Die auftretenden Events sind dabei die gleichen
wie bei einem Trigger: Ändern, Löschen, Einfügen und Lesen von Objekten.
117
Neben der pessimistischen Nebenläufigkeitskontrolle existiert in FastObjects die
Möglichkeit, eine (automatische) optimistische Nebenläufigkeitskontrolle zu verwenden, die in einer relationalen oder objektrelationalen Datenbank nur durch zusätzliche Attribute und manuell realisiert werden kann. Unter Umständen kann es sinnvoll
sein, die Daten nicht unbedingt gleich zu sperren oder die Transaktionen zu serialisieren. Trotzdem soll aber gesichert sein, dass keine inkonsistenten Zustände auftreten.
Eine Möglichkeit, die persistenten Klassen im Klassenmodell zu kennzeichnen,
könnte ein Stereotyp sein (beispielsweise persistent). Das Klassenmodell könnte in
der Analyse entwickelt und im Entwurf verfeinert werden. Für die Implementierung
muss dieses dann nicht mehr geändert werden.
Des Weiteren bietet die FastObject .NET Datenbank noch Mechanismen zum
sekundären Datenmanagement an. Recovery wird nach eigenen Angaben ebenfalls
unterstützt, d. h., im Fall eines Ausfalls wird der alte (konsistente) Zustand wieder
hergestellt.
9.2
Persistenz Framework und Datenbankvergleich
Das in Kapitel 5.3 entwickelte Framework sollte einen Vergleich von relationaler und
objektrelationaler Datenbank ermöglichen. Das Problem, was hierbei bestand, war,
dass durch diese Struktur von vornherein ein objektiver Vergleich ausgeschlossen
ist. Eines der zentralen Konzepte der relationalen Datenbank ist die Vererbung.
Dadurch, dass jedes konkrete persistente Objekt und jeder konkrete Manager von
einer entsprechenden Klasse abgeleitet werden musste, war in dieser Struktur von
vornherein kein objektiver Vergleich möglich.
9.3
Entwicklungsprozess
Die Vorgehensweise, zunächst eine relationale Datenbank zu verwenden und anschließend die gleiche Anwendung mit einer besseren Variante, wie beispielsweise
einer objektorientierten Datenbank, zu realisieren, stellte sich ebenfalls nicht als
vorteilhaft heraus.
Folgendes Szenario soll den Grund dafür verdeutlichen:
1. Eine Änderungen der Anforderungen wird verlangt (siehe Kapitel Prototyping
in Kapitel 3.1.5).
2. Diese Änderung musste (manuell) überprüft werden (siehe Kapitel 3.2).
3. Anschließend wurden diese Änderungen (halb)automatisch in das Requirements Document übernommen (siehe Kapitel 3.4).
118
4. Das ERwin-Datenmodell wurde angepasst (siehe Kapitel 6.7.2).
5. Das entsprechende informative Datenmodell wurden angepasst (siehe Kapitel
3.3.1).
6. Die Struktur des Persistenz-Frameworks wurde geändert (siehe Kapitel 5.3.5).
7. Diese Änderung muss in der konkreten Komponente, welche die Implementierung mit der relationalen Datenbank vornimmt, geändert werden.
Wäre die erste Wahl für die verwendete Datenbanktechnik eine objektorientierte
Datenbank gewesen, so wären nur die ersten drei Schritte und eine Anpassung an
ein Klassen-/Datenmodell nötig gewesen.
9.4
Zusammenfassung der wichtigsten Erkenntnisse
Im Folgenden werden die wichtigsten Erkenntnisse stichpunktartig zusammengefasst:
• Für die Verwaltung der Requirements ein unterstützendes Tool verwenden.
• Die Systemgrenzen ganz genau abgrenzen und genau definieren, wo die Anwendung nicht mehr weitermacht.
• Ein nicht unwesentliches Maß an ”Fingerspitzengefühl”, Intuition und Erfahrung ist beim Requirements Engineering immer nötig und kann auch nicht
durch Erlernen von bestimmten Techniken ersetzt werden.
• Die Entwicklung eines Frameworks ist kompliziert, da es schwierig ist, alle
möglichen Aspekte vorherzusehen.
• Die Verwendung eine Frameworks ist einfach, wenn man die Schnittstelle genau
kennt.
• Das Ziel genau spezifizieren und nicht aus den Augen verlieren.
• Eine Web-Applikation besitzt nicht nur Vorteile (siehe Abbildung 29 auf Seite
54).
• Bei der Modellierung mit einer relationalen Datenbank sollte auf zusammengesetzte Schlüssel verzichtet werden. Ausnahme ist die Abbildung einer m:nBeziehung.
119
9.5
Offene Frage
Eines der Hauptprobleme war, die verschiedenen Modellierungstechniken, wie in Kapitel 9.3 beschrieben, konsistent zueinander zu halten. Sowohl die Trennung nach
dem Model View Controller Pattern als auch die Trennung von Datenbank und Anwendung hat Vor- und Nachteile.
Vorteile:
• Die Komponenten lassen sich einfach austauschen bzw. ersetzen.
• Eine Komponente enthält nur einen bestimmten Aspekt eines Problems, wie
beispielsweise die Steuerung der Benutzeroberfläche oder die Datenstruktur.
Nachteil:
• Es existieren redundante Informationen in den verschiedenen Modellen, d.h.,
eine Änderung wird eventuell an mehreren Stellen durchgeführt.
Der andere Weg wäre, zunächst die Anforderungen zu erheben, diese zu überprüfen, und erst wenn alle die Requirement ”fehlerfrei” sind, zum Entwurf überzugehen.
Das Problem ist nur, wie realistisch ist die Anforderung, dass eine Requirement ”fehlerfrei” ist?
Existiert für das in Abbildung 77 dargestellte Fragezeichen eine brauchbare Lösung?
120
Abbildung 77: Auswirkung einer Anforderungsänderung (vgl. mit Kapitel 9.3)
121
Literatur
[Ade 94] IDEF-1X - Eine Methode zur Datenmodellierung
H.H. Adelsberger, F. Körner, 1994, Universität GH Essen
[Atk+ 95] The Object-Oriented Database System Manifesto, 1995
M. Atkinson, F. Bancilhon, D. DeWitt, K. Dittrich, D. Maier, S. Zdonik
www-2.cs.cmu.edu/People/clamen/OODBMS/Manifesto/htManifesto/Manifesto.html
[Bit Koc 00] Objektorientierte Analyse und Design
Die Fusion-Methode unter Verwendung von UML,
M. Bittner und W. Koch, 2000
[CIS] Normalisierung
Begleitende Folien zur Vorlesung Datenbanksysteme (DBS)
im Fachbereich Computergestützte InformationsSysteme (CIS)
an der Technischen Universität Berlin (TUB)
[Cod 70] A Relational Model of Data for Large Shared Data Banks
E. F. Codd, 1970
http://www.acm.org/classics/nov95/
[Con 99] Modeling Web Application Architectures with UML
Rational Software White Paper
J. Conallen, Rational Software, June 1999
[Eis+ 99] SQL:1999, formerly known as SQL3
A. Eisenberg, J. Melton , 1999
[Esp 04] Das ASP.NET-Seitenobjektmodell
MSDN, Entwickler Bibliothek
D. Esposito, 2004
[Ett 99] IDEF1X VS UML
A Comparative Analysis
B.Ettlinger, 1999, Artikel aus ”The Erwin Insider”
(Tips, Tricks and Articles of Interest to ERwin and BPwin Users)
[FO 04a] FastObjects .NET
Script zur Schulung ”Einführungs-Workshop C#”
08.01.2004
[FO 04b] FastObjects .NET Programmer’s Guide
Poet Software, 2004
[Fra+ 96] Delegation:
Eine sinnvolle Ergänzung gängiger objektorientierter Modellierungskonzepte
U. Frank, S. Halter, 1996
122
[Fin 02] Anbindung objektorientierter Software an objektrelationale Datenbanken
Diplomararbeit an der Universität Hamburg im Fachbereich Softwaretechnik
M. Finsterwalder, 2002
[Geb 04] Datenbanken
Prof. Dr. K.F. Gebhardt, 2004
[Gli 04] Spezifikation und Entwurf von Software
Vorlesung im WS 2003/2004 von Prof. Dr. M. Glinz (Institut für Informatik
der Universität Zürich)
http://www.ifi.unizh.ch/groups/req/courses/ses/
[GotDotNet] http://de.gotdotnet.com/quickstart/aspplus/doc/authandauth.aspx
[IDEF] IDEF Family of Methods
Knowledge Based Systems, Inc
http://www.idef.com
[IEEE610.12-1990] IEEE Standard Glossary of Software Engineering Terminology,
IEEE Std.610.12-1990
[IEEE830-1998] IEEE Recommended Practice for Software Requirements Specifications,
IEEE Std 830-1998
[Inf 99] SQL Reference Guide, Version 6.0, 1999
[Lau 01] Object-Oriented Features of SQL:1999 Workshop-Folien,
F. Laux, 2001
[Lin 01] Dynamisches Verhalten in UML Dynamisches Verhalten in UML
Prof. Dr. rer. nat N. Link, WS 2001/2002, LKIT an der FH Karlsruhe
[Loh 03] Einstieg in ASP.NET,
Für Einsteiger und Umsteiger,
M. Lohrer, Galileo Computing, 2003
[Luf 99] Beitrag im Informatik-Lexikon der Gesellschaft für Informatik e.V.,
J. Lufter, 1999
[Luf 02] Abbildung normkonformer objektrelationaler Sprachmittel auf reale DBMS,
J. Lufter, 2003
[MSDN] Microsoft Developer Network
http://msdn.microsoft.com/
123
[MSDN ASP.NET] ASP.NET Technology Backgrounder
Microsoft Corporation, 2001
msdn.microsoft.com/library/en-us/vbcon/html/vbconasptechnologybackgrounder.asp
[MSDN .NET Framework FAQ 01] Microsoft .NET Framework FAQ
Microsoft Corporation, 2001
http://msdn.microsoft.com/library/en-us/dndotnet/html/faq111700.asp
[Mös 03] Vorlesung im Institut für Systemsoftware
an der Johannes Kepler Universität (JKU) Linz, Österreich
”Softwareentwicklung mit C#”
Institut für Systemsoftware, Fachbereich Informatik
Johannes Kepler Universität Linz
H. Mössenböck, 2003
http://www.ssw.uni-linz.ac.at/Teaching/Lectures/CSharp/
[NetLexikon] Net-Lexikon
http://www.net-lexikon.de
[Pla 03] Implementierung von Datenbanktransaktionen mit Microsoft .NET,
M. Platt, 2003, Artikel aus der MSDN Entwickler Bibliothek
[ReqDoc] Requirements Dokument zu dieser Diplomarbeit
C. Schweter, 2004
[Rup 01] Requirement Engineering - der Einsatz natürlichsprachlicher Methoden bei
der Ermittlung und Qualitätsprüfung von Anforderungen,
C. Rupp, Paper 2001
[Rup 02] Requirements-Engineering und -Management C. Rupp, Hanser-Verlag,
2002
[Saa 03] Objektdatenbanken, 2003
Gunter Saake, Can Türker, Ingo Schmitt
[Sah 00] Anforderungsanalyse für die Werkzeugunterstützung der Methode FUSION
und Entwurf einer Benutzungsschnittstelle
B. Sahin, Diplomarbeit im Fachgebiet Softwaretechnik,
Technischen Universität Berlin, 2000
[Sch 02] Einsatz von Applikationsservern
Untersuchung am Beispiel des Sybase ”Enterprise Application Server”
Diplomarbeit an der FH Brandenburg, FB Informatik und Medien,
A. Schwarzbauer, 2002
http://ots.fh-brandenburg.de -> abgeschlossene Diplomarbeiten
124
[Scr+ 97] Object persistence in object-oriented applications
Artikel aus dem IBM Systems Journal, Vol. 36,
V.Srinivasan, D. T. Chang
[Som 00] Software Engineering 6th Edition
Powerpoint Presentations von Ian Sommervielle zum gleichnamigen Buch
http://www.comp.lancs.ac.uk/computing/resources/SE6/Slides/
[Som Saw 97] Requirements Engineering - A good practice guide
Ian Sommerville und Pete Sawyer, 1997
[Tür 03] SQL:1999 & SQL:2003
Objektrelationales SQL, SQLJ & SQL/XML, 2003
Can Türker, 2003
[UML] UML Notation Guide
OMG-Unified Modeling Language, v1.5, 2003
[ViSEK] Virtuelles Software Engineering Kompetenzzentrum
http://www.visek.de
[Vor 99] Unterlagen zur Vorlesung Datenbanksysteme
22.Juli 1999, Oliver Vornberger
Universität Osnabrück Fachbereich Mathematik und Informatik Praktische Informatik
125
A
Requirements Document
126
Herunterladen