Praktikum angewandte Systemsoftwaretechnik - Exam
Aufgabe 1)
Stellen Sie sich vor, Sie sind als Projektleiter für ein neues Softwareentwicklungsprojekt verantwortlich. Es geht darum, eine Anwendung zu entwickeln, die eine umfassende Datenbank zur Verwaltung von Kundeninformationen eines Unternehmens bietet. Ihr Unternehmen hat bereits das Grundkonzept skizziert, aber nun müssen Sie die Anforderungsanalyse und die Projektplanung durchführen. Ihnen steht ein multidisziplinäres Team aus Entwicklern, Designern und Analysten zur Verfügung.
a)
Anforderungsanalyse: Erläutern Sie die Schritte, die Sie unternehmen würden, um die Anforderungen an die neue Anwendung zu identifizieren. Berücksichtigen Sie dabei die verschiedenen Typen von Anforderungen und wie diese dokumentiert werden sollten. Welche Methoden und Hilfsmittel würden Sie nutzen, um die Anforderungen zu sammeln und zu priorisieren?
Lösung:
Anforderungsanalyse:
Um die Anforderungen an die neue Anwendung zu identifizieren und zu dokumentieren, folge ich einem systematischen Schritt-für-Schritt-Ansatz:
- Schritt 1: Einführungs- und Informationsphase: In dieser Phase führe ich Einführungsmeetings mit den Stakeholdern (zum Beispiel Management, Kunden und Endnutzer) durch, um ein Verständnis für das Gesamtziel des Projekts zu erhalten. Es ist wichtig, die Vision und die Geschäftsziele klar zu definieren.
- Schritt 2: Erhebung von Anforderungen: Ich verwende verschiedene Methoden, um die Anforderungen zu erfassen:
- Interviews: Einzel- oder Gruppeninterviews mit Stakeholdern, um deren Bedürfnisse und Wünsche zu verstehen.
- Workshops: Gemeinsame Workshops mit Interessengruppen, um Anforderungen in einem kooperativen Umfeld zu erarbeiten.
- Fragebögen: Standardisierte Fragebögen, um systematisch Informationen von einer großen Zielgruppe zu sammeln.
- Beobachtungen: Direkte Beobachtungen der Benutzer in ihrer Arbeitsumgebung, um deren Arbeitsabläufe zu verstehen.
- Dokumentenüberprüfung: Analyse bestehender Dokumentationen, wie Geschäftsprozesse und bestehende Softwaresysteme.
- Schritt 3: Klassifizierung und Dokumentation der Anforderungen: Die Anforderungen werden nach verschiedenen Typen klassifiziert:
- Funktionale Anforderungen: Diese beschreiben, welche Funktionen und Features die Anwendung haben muss (z.B. Benutzerverwaltung, Berichtserstellung).
- Nicht-funktionale Anforderungen: Diese betreffen Qualitätsattribute wie Leistung, Sicherheit und Benutzerfreundlichkeit.
- Geschäftsanforderungen: Diese umfassen übergeordnete Geschäftsziele und Projektvorgaben.
- Technische Anforderungen: Diese beziehen sich auf die technischen Voraussetzungen, wie Plattformen, Softwareumgebungen oder Schnittstellen zu anderen Systemen.
- Regulatorische Anforderungen: Auflagen und gesetzliche Vorgaben, die eingehalten werden müssen.
Jede dieser Anforderungstypen wird in einem Anforderungsdokument (Requirements Specification Document) detailliert beschrieben und inklusive Akzeptanzkriterien dokumentiert. - Schritt 4: Anforderungsanalyse und Überprüfung: Ich werde regelmäßige Überprüfungen und Verifikationssitzungen mit Stakeholdern durchführen, um sicherzustellen, dass die gesammelten Anforderungen korrekt und relevant sind. Hierzu wird es hilfreich sein, Use Cases und User Stories zu erstellen.
- Schritt 5: Priorisierung der Anforderungen: Mithilfe von Methoden wie Moscow (Must have, Should have, Could have, Won't have) oder Kano-Modell werde ich die Anforderungen priorisieren, um die wichtigsten Funktionen und Features zuerst zu entwickeln und zu implementieren.
- Schritt 6: Continuous Review: Es ist wesentlich, die Anforderungen kontinuierlich zu überprüfen und bei Bedarf anzupassen. Dies kann durch regelmäßige Sprint-Reviews und Feedback-Schleifen im Rahmen agiler Entwicklungsmethoden wie Scrum erfolgen.
Zusammengefasst ist eine strukturierte und umfassende Anforderungsanalyse der Schlüssel zum Erfolg des Projekts. Durch den Einsatz verschiedener Methoden zur Sammlung und Priorisierung von Anforderungen stelle ich sicher, dass die entwickelte Anwendung den Bedürfnissen der Benutzer und den Geschäftszielen des Unternehmens entspricht.
b)
Dokumentation: Erstellen Sie ein Beispieldiagramm (z.B. Use-Case-Diagramm) und eine kurze Beschreibung, die die wichtigsten Funktionalitäten der neuen Anwendung skizzieren. Wie würden Sie sicherstellen, dass alle Anforderungen ordnungsgemäß dokumentiert und verständlich für das gesamte Team sind?
Lösung:
Dokumentation:
Um die wichtigsten Funktionalitäten der neuen Anwendung zu skizzieren und sicherzustellen, dass alle Anforderungen ordnungsgemäß dokumentiert und für das gesamte Team verständlich sind, werde ich ein Use-Case-Diagramm erstellen und eine kurze Beschreibung der Funktionalitäten geben.
Use-Case-Diagramm:
Beschreibung des Use-Case-Diagramms:
- Benutzerverwaltung: Ermöglicht die Anlage, Bearbeitung und Löschung von Benutzerkonten inklusive Rollenzuweisungen (Administrator, Mitarbeiter).
- Kundenstammdatenverwaltung: Erfasst und pflegt grundlegende Informationen zu Kunden wie Name, Adresse, Kontaktdaten und Firmendaten.
- Kundenhistorie: Speichert und zeigt die Interaktionshistorie mit Kunden, inklusive Anfragen, Beschwerden und Transaktionen.
- Berichtserstellung: Generiert Standard- und benutzerdefinierte Berichte über Kundendaten und -aktivitäten für Managementzwecke.
- Sicherheit: Beinhaltet Authentifizierung und Autorisierung, um sicherzustellen, dass nur berechtigte Benutzer auf bestimmte Daten zugreifen können.
Um sicherzustellen, dass alle Anforderungen verständlich und ordnungsgemäß dokumentiert sind, verwende ich die folgenden Methoden und Hilfsmittel:
- Requirements Specification Document (RSD): Ein umfassendes Dokument, das alle funktionalen und nicht-funktionalen Anforderungen enthält. Jede Anforderung wird mit einer eindeutigen ID, einer detaillierten Beschreibung, Akzeptanzkriterien und Prioritäten versehen.
- Use Case Beschreibungen: Für jeden Use Case wird eine detaillierte Beschreibung erstellt, die den Akteuren, den Zielsetzungen, den Vorbedingungen, dem normalen Ablauf, den alternativen Abläufen und den Nachbedingungen beschreibt.
- Mockups und Wireframes: Visuelle Darstellungen der Benutzeroberfläche, die den Designern und Entwicklern helfen, ein gemeinsames Verständnis der Anforderungen und des erwarteten Endprodukts zu haben.
- Regelmäßige Meetings und Reviews: Regelmäßige Anforderungs- und Design-Reviews mit dem gesamten Team, um sicherzustellen, dass alle Anforderungen verstanden und korrekt implementiert werden.
- Agile Boards (z.B. Trello, JIRA): Einsatz von agilen Projektmanagement-Tools, um Anforderungen in kleinere Aufgaben zu unterteilen und deren Fortschritt zu verfolgen.
Durch diese Methodik stelle ich sicher, dass alle Anforderungen klar, vollständig und für das gesamte Team verständlich sind, und damit die Grundlage für eine erfolgreiche Umsetzung des Projekts geschaffen wird.
c)
Projektplanung: Entwerfen Sie einen groben Zeitplan für das Projekt, in dem Sie Meilensteine und Deadlines festlegen. Welche Faktoren würden Sie bei der Bestimmung von Personal, Zeit und Budget berücksichtigen? Berechnen Sie die ungefähren Kosten basierend auf festen Tagessätzen und einer geschätzten Anzahl von Arbeitstagen.
Lösung:
Projektplanung:
Ein grober Zeitplan für das Projekt mit definierten Meilensteinen und Deadlines könnte wie folgt aussehen:
Grobzeitplan:
- Projektvorbereitungsphase (2 Wochen): Kick-Off-Meeting, Teamzusammenstellung, detaillierte Anforderungsanalyse
- Planungs- und Entwurfsphase (4 Wochen): Erstellung eines detaillierten Projektplans, Systementwurf, Erstellung von Wireframes und Mockups
- Implementierungsphase-1 (8 Wochen): Entwicklung der Kernfunktionalitäten (Benutzerverwaltung, Kundenstammdatenverwaltung)
- Implementierungsphase-2 (8 Wochen): Erweiterung um zusätzliche Funktionalitäten (Kundenhistorie, Berichtserstellung, Sicherheit)
- Testphase (4 Wochen): Interne Tests, Benutzertests, Fehlerbehebung und Optimierung
- Bereitstellungs- und Übergabephase (2 Wochen): Deployment, Schulung der Endnutzer, Projektdokumentation und Abschluss
Meilensteine und Deadlines:
- Meilenstein 1: Anforderungsanalyse abgeschlossen – Woche 2
- Meilenstein 2: Detaillierter Projektplan erstellt – Woche 6
- Meilenstein 3: Kernfunktionalitäten entwickelt – Woche 14
- Meilenstein 4: Erweiterte Funktionalitäten entwickelt – Woche 22
- Meilenstein 5: Testphase abgeschlossen – Woche 26
- Meilenstein 6: Projekt bereitgestellt – Woche 28
Faktoren zur Bestimmung von Personal, Zeit und Budget:
- Projektumfang: Anzahl und Komplexität der Funktionen und Anforderungen
- Teamgröße und Zusammensetzung: Verfügbarkeit von Entwicklern, Designern und Analysten
- Erfahrung und Fähigkeitsniveau des Teams: Höhere Frühere Projekte, Fachwissen etc.
- Zeitplan: Geplante Deadlines und Flexibilität des Enddatums
- Budget: Verfügbarkeit von finanziellen Ressourcen, feste Tagessätze
- Risk Management: Identifikation möglicher Risiken und Festlegung von Pufferzeiten zur Risikoabsicherung
Kostenberechnung:
Angenommen, wir haben ein Team von insgesamt 5 Personen (2 Entwickler, 1 Designer, 1 Analyst, 1 Projektleiter) und gehen von festen Tagessätzen aus:
- Entwickler: 500 EUR/Tag
- Designer: 400 EUR/Tag
- Analyst: 450 EUR/Tag
- Projektleiter: 600 EUR/Tag
Schätzungen für die Anzahl der Arbeitstage pro Phase:
- Projektvorbereitungsphase: 10 Arbeitstage 2 Entwickler x 10 Tage x 500 EUR/Tag = 10.000 EUR 1 Designer x 10 Tage x 400 EUR/Tag = 4.000 EUR 1 Analyst x 10 Tage x 450 EUR/Tag = 4.500 EUR 1 Projektleiter x 10 Tage x 600 EUR/Tag = 6.000 EUR Summe: 24.500 EUR
- Planungs- und Entwurfsphase: 20 Arbeitstage 2 Entwickler x 20 Tage x 500 EUR/Tag = 20.000 EUR 1 Designer x 20 Tage x 400 EUR/Tag = 8.000 EUR 1 Analyst x 20 Tage x 450 EUR/Tag = 9.000 EUR 1 Projektleiter x 20 Tage x 600 EUR/Tag = 12.000 EUR Summe: 49.000 EUR
- Implementierungsphase-1: 40 Arbeitstage 2 Entwickler x 40 Tage x 500 EUR/Tag = 40.000 EUR 1 Designer x 10 Tage x 400 EUR/Tag = 4.000 EUR 1 Analyst x 10 Tage x 450 EUR/Tag = 4.500 EUR 1 Projektleiter x 40 Tage x 600 EUR/Tag = 24.000 EUR Summe: 72.500 EUR
- Implementierungsphase-2: 40 Arbeitstage 2 Entwickler x 40 Tage x 500 EUR/Tag = 40.000 EUR 1 Designer x 10 Tage x 400 EUR/Tag = 4.000 EUR 1 Analyst x 10 Tage x 450 EUR/Tag = 4.500 EUR 1 Projektleiter x 40 Tage x 600 EUR/Tag = 24.000 EUR Summe: 72.500 EUR
- Testphase: 20 Arbeitstage 2 Entwickler x 20 Tage x 500 EUR/Tag = 20.000 EUR 1 Designer x 5 Tage x 400 EUR/Tag = 2.000 EUR 1 Analyst x 15 Tage x 450 EUR/Tag = 6.750 EUR 1 Projektleiter x 20 Tage x 600 EUR/Tag = 12.000 EUR Summe: 40.750 EUR
- Bereitstellungs- und Übergabephase: 10 Arbeitstage 2 Entwickler x 10 Tage x 500 EUR/Tag = 10.000 EUR 1 Designer x 5 Tage x 400 EUR/Tag = 2.000 EUR 1 Analyst x 5 Tage x 450 EUR/Tag = 2.250 EUR 1 Projektleiter x 10 Tage x 600 EUR/Tag = 6.000 EUR Summe: 20.250 EUR
Gesamtkosten: 24.500 EUR + 49.000 EUR + 72.500 EUR + 72.500 EUR + 40.750 EUR + 20.250 EUR = 279.500 EUR
Durch die sorgfältige Berücksichtigung dieser Faktoren und die detaillierte Planung können wir einen realistischen Zeit- und Budgetrahmen festlegen, der die erfolgreiche Durchführung des Projekts unterstützt.
d)
Risikoanalyse: Identifizieren Sie potentielle Risiken, die während des Projekts auftreten könnten. Entwickeln Sie eine Strategie, wie diese Risiken überwacht und gemindert werden können. Wie würden Sie das Team und die Stakeholder regelmäßig über den Fortschritt und mögliche Risiken informierten?
Lösung:
Risikoanalyse:
Bei der Durchführung eines Softwareentwicklungsprojekts können verschiedene Risiken auftreten. Einige potentielle Risiken und Strategien zu deren Überwachung und Minderung sind nachfolgend aufgeführt:
Potentielle Risiken und Strategien zur Minderung:
- Unklare Anforderungen: Unklare oder sich ändernde Anforderungen können zu Projektverzögerungen und Fehlentwicklungen führen. Strategie: Regelmäßige Anforderungsworkshops, kontinuierliche Kommunikation mit Stakeholdern und die Verwendung von Use-Case-Diagrammen und User Stories zur klaren Dokumentation der Anforderungen.
- Technologische Risiken: Probleme bei der Implementierung neuer Technologien oder das Versagen technischer Komponenten. Strategie: Technologisches Risikoassessment, Prototyping, Schulungen und regelmäßige Updates der Softwareumgebung.
- Personalausfälle: Unvorhersehbare Personalausfälle durch Krankheit oder Kündigungen. Strategie: Schaffung eines flexiblen und vielseitigen Teams, klar definierte Vertretungsregelungen, Dokumentation von Wissen und Cross-Training der Teammitglieder.
- Budgetüberschreitungen: Unvorhergesehene Kosten können das Projektbudget überschreiten. Strategie: Genaue Budgetplanung, regelmäßige Kostenkontrolle und Einführung eines Pufferbudgets zu Beginn des Projekts.
- Projektverzögerungen: Verzögerungen bei der Entwicklung können die Einhaltung von Deadlines gefährden. Strategie: Realistische Zeitplanung, regelmäßige Fortschrittsüberprüfungen, agile Projektmanagementmethoden und Implementierung von Pufferzeiten.
- Qualitätsprobleme: Die Software erfüllt nicht die geforderten Qualitätsstandards. Strategie: Implementierung eines Qualitätsmanagementplans, kontinuierliche Tests während der Entwicklung, Code Reviews und Benutzerakzeptanztests (UAT).
Überwachung und Minderung der Risiken:
- Risiko-Register: Erstellen und pflegen eines Risiko-Registers, das alle identifizierten Risiken, deren Eintrittswahrscheinlichkeit, potenzielle Auswirkungen sowie die entsprechenden Maßnahmen zur Minderung dokumentiert.
- Regelmäßige Risiko-Reviews: Wöchentliche oder zweiwöchentliche Meetings zur Überprüfung der aktuellen Risiken und zur Bewertung neuer potenzieller Risiken.
- Risk-Owner: Zuweisung von Verantwortlichkeiten für jedes identifizierte Risiko an spezifische Teammitglieder, die für die Überwachung und Steuerung dieses Risikos verantwortlich sind.
- Frühwarnsysteme: Implementierung eines Systems zur schnellen Erkennung von Warnsignalen, die auf das Eintreten eines Risikos hinweisen (z.B. durch Kennzahlen oder Key Performance Indicators).
Kommunikation mit dem Team und den Stakeholdern:
- Regelmäßige Statusberichte: Wöchentliche Statusberichte, die den Fortschritt, die erreichten Meilensteine, die aktuellen Risiken und die getroffenen Maßnahmen zur Risikominderung beinhalten.
- Projekt-Stand-Up-Meetings: Tägliche kurze Meetings, in denen das Team den aktuellen Stand, auftretende Probleme und notwendige Unterstützung kommuniziert.
- Stakeholder-Meetings: Monatliche oder zweiwöchentliche Meetings mit den Stakeholdern, um über den Fortschritt zu berichten, Feedback zu erhalten und eventuelle Änderungen in den Anforderungen zu besprechen.
- Projektdokumentation: Laufende Dokumentation aller wichtigen Entscheidungen, Projektänderungen und Fortschritte in einem zentralen Projektplanungs- und Dokumentationstool (z.B. Confluence, JIRA).
- Transparenz schaffen: Erstellen eines Dashboards, das den aktuellen Projektstatus, die wichtigsten Meilensteine und die identifizierten Risiken transparent für alle Teammitglieder und Stakeholder darstellt.
Durch den Einsatz dieser Strategien und Kommunikationsmethoden können die Risiken im Projekt effektiv überwacht und gemindert werden, während alle Beteiligten stets gut informiert und eingebunden sind.
Aufgabe 2)
Versionskontrollsysteme (VCS) wie Git sind essentielle Werkzeuge in der Softwareentwicklung, um Änderungen an Quellcode und anderen Sammlungen digitaler Daten über die Zeit zu verwalten. Git ist ein weit verbreitetes VCS, das sowohl lokale als auch entfernte Repositories unterstützt. Zu den zentralen Konzepten und Befehlen von Git gehören Commits, Branches und das Zusammenführen von Branches (Merging).
Du sollst im Folgenden zwei Aufgaben zu Git beantworten, um dein Verständnis und Wissen in Bezug auf den praktischen Einsatz von Versionskontrollsystemen zu zeigen.
a)
Stelle dir vor, du hast ein lokales Git-Repository initialisiert und arbeitest an zwei Features in separaten Branches: feature-a
und feature-b
. Beschreibe den genauen Ablauf, um die Änderungen von feature-a
in den Hauptbranch main
zu integrieren, inklusive der genauen Git-Befehle, die du verwenden würdest. Erkläre dabei auch, wie du dabei mögliche Merge-Konflikte lösen kannst.
Lösung:
Schritt-für-Schritt Anleitung zum Mergen von feature-a
in main
:
- 1. Stelle sicher, dass du dich im Hauptbranch
main
befindest:
git checkout main
2. Ziehe die neuesten Änderungen aus dem entfernten Repository (falls andere Entwickler Änderungen gepusht haben): git pull origin main
3. Mergiere den Branch feature-a
in den Hauptbranch main
: git merge feature-a
Umgang mit Merge-Konflikten:
- 1. Sollte es Merge-Konflikte geben, werden diese in der Ausgabe des Merge-Befehls angezeigt:
Auto-merging datei.xyzCONFLICT (content): Merge conflict in datei.xyzAutomatic merge failed; fix conflicts and then commit the result.
2. Öffne die Datei(en) mit Konflikten in einem Texteditor und behebe die Konflikte manuell: git mergetool
3. Markiere die Konflikte als behoben durch hinzufügen der Datei(en) zur Staging-Area: git add datei.xyz
4. Vervollständige den Merge-Prozess durch Erstellen eines Commit für den Merge: git commit
Falls du den Merge abbrechen möchtest, kann dies mit folgendem Befehl durchgeführt werden:
- 1. Abbrechen des Merges und Rückkehr zum vorherigen Zustand:
git merge --abort
b)
Ein Teammitglied hat ein Remote-Repository auf einem Server erstellt und teilt die URL mit dir. Schreibe den genauen Ablauf, wie du dieses Repository auf deinen lokalen Rechner klonst, eine Änderung in einer Datei durchführst und diese Änderung erfolgreich zurück in das Remote-Repository überträgst. Verwende dabei die korrekten Git-Befehle und erkläre kurz, was jeder Befehl bewirkt.
Lösung:
Schritt-für-Schritt Anleitung zum Klonen eines entfernten Repositories, Durchführen einer Änderung und Zurückübertragen:
- 1. Klonen des Remote-Repositorys auf deinen lokalen Rechner:
git clone URL-des-Remote-Repositorys
Erklärung: git clone
erstellt eine lokale Kopie des angegebenen Remote-Repositorys.
2. Wechsel in das Verzeichnis des geklonten Repositorys: cd Verzeichnisname
Erklärung: cd
wechselt in das Verzeichnis des lokalen Repositorys.
3. Bearbeiten einer Datei im Repository: [Öffne eine Datei und führe eine Änderung durch]
echo 'Eine Änderung' >> dateiname
Erklärung: Mit diesem Befehl wird eine Zeile mit dem Text „Eine Änderung“ an die Datei
dateiname
angefügt. Dies ist ein Beispiel. Du kannst beliebige Änderungen an der Datei vornehmen.
4. Hinzufügen der geänderten Datei(en) zur Staging-Area: git add dateiname
Erklärung: git add
fügt die Änderungen in der angegebenen Datei der Staging-Area hinzu, d. h., sie werden für den nächsten Commit vorgemerkt.
5. Erstellen eines neuen Commits mit einer Beschreibung der Änderung: git commit -m „Beschreibung der Änderung“
Erklärung: git commit
erstellt einen neuen Commit mit den Änderungen in der Staging-Area. Die Option
-m
ermöglicht das Hinzufügen einer kurzen Beschreibung, die die Änderungen beschreibt.
6. Übertragen des Commits in das Remote-Repository: git push origin main
Erklärung: git push
überträgt die lokalen Commits zu dem Remote-Repository. Die Angabe
origin
verweist auf das Standard-Remote-Repository und
main
auf den Hauptbranch.
Aufgabe 3)
Du bist verantwortlich für die Qualitätssicherung eines neuen Softwareprojekts in Deinem Unternehmen. Das Projekt umfasst die Implementierung einer Webanwendung, die es Kunden ermöglicht, online Bestellungen aufzugeben. Um eine hohe Softwarequalität sicherzustellen, müssen verschiedene Teststrategien und -techniken angewendet werden.
a)
a) Erkläre die Unterschiede zwischen Unit-Tests, Integrationstests, Systemtests und Akzeptanztests. Gib für jede Testart ein Beispiel, wie Du diese für die Webanwendung einsetzen könntest.
Lösung:
Um die Softwarequalität sicherzustellen, ist es wichtig, verschiedene Teststrategien und -techniken anzuwenden. Hier sind die Unterschiede zwischen Unit-Tests, Integrationstests, Systemtests und Akzeptanztests, zusammen mit Beispielen, wie Du sie für eine Webanwendung einsetzen kannst:
- Unit-Tests: Beschreibung: Unit-Tests testen einzelne Komponenten oder Module des Codes isoliert. Sie sind darauf ausgelegt, die kleinste Testbare Einheit der Anwendung zu überprüfen, z.B. eine Methode oder Funktion. Beispiel: Angenommen, die Webanwendung hat eine Funktion zur Berechnung eines Rabatts für eine Bestellung. Ein Unit-Test könnte überprüfen, ob diese Funktion den richtigen Rabatt basierend auf dem Bestellbetrag und den Rabattrichtlinien berechnet.
- Integrationstests: Beschreibung: Integrationstests überprüfen das Zusammenspiel mehrerer Komponenten oder Module, um sicherzustellen, dass sie zusammenarbeiten wie erwartet. Beispiel: In der Webanwendung könnte ein Integrationstest überprüfen, ob die Anmeldung eines Benutzers korrekt funktioniert, indem er sicherstellt, dass die Anmeldungskomponente korrekt mit der Benutzerdatenbank und dem Authentifizierungsmodul interagiert.
- Systemtests: Beschreibung: Systemtests prüfen das gesamte System als Ganzes. Sie testen das integrierte System gegen die Anforderungsspezifikationen, um sicherzustellen, dass das gesamte System richtig funktioniert. Beispiel: Ein Systemtest für die Webanwendung könnte den gesamten Bestellvorgang betreffen: Ein Benutzer wählt Produkte aus, legt sie in den Warenkorb, geht zur Kasse, gibt Versandinformationen ein und schließt die Bestellung ab. Der Test würde sicherstellen, dass all diese Schritte nahtlos und fehlerfrei ablaufen.
- Akzeptanztests: Beschreibung: Akzeptanztests werden durchgeführt, um sicherzustellen, dass das System den Geschäftsanforderungen und -spezifikationen des Kunden entspricht. Sie sind in der Regel die letzte Teststufe vor der Freigabe des Systems. Beispiel: Ein Akzeptanztest für die Webanwendung könnte eine Validierung sein, dass die Anwendung wie von den Stakeholdern gefordert, die Bestellbestätigungen per E-Mail korrekt verschickt und die Bestellhistorie des Benutzers richtig anzeigt.
b)
b) Diskutiere die Vor- und Nachteile von Black-Box-Testing, White-Box-Testing und Graue-Box-Testing. Welche dieser Testtechniken würdest Du für die verschiedenen Testphasen der Webanwendung verwenden und warum?
Lösung:
Beim Testen einer Webanwendung gibt es verschiedene Testtechniken, die jeweils ihre eigenen Vor- und Nachteile haben. Hier sind die Unterschiede und die empfohlenen Einsatzbereiche von Black-Box-Testing, White-Box-Testing und Graue-Box-Testing:
- Black-Box-Testing: Beschreibung: Black-Box-Testing konzentriert sich auf die Funktionalität der Software ohne Kenntnis der internen Implementierung. Tester erstellen Testfälle basierend auf Spezifikationen und Anforderungen. Vorteile:
- Unabhängig von der Codebasis
- Kann von nicht technischen Personen durchgeführt werden
- Hilfreich zur Validierung der Software gegen die Anforderungen
Nachteile: - Begrenzte Testabdeckung auf interne Fehler
- Kann ineffizient sein, wenn die Spezifikationen unklar sind
- Schwierigkeit bei der Reproduktion interner Fehler
Verwendung: Black-Box-Tests sind ideal für Akzeptanz- und Systemtests, da sie die Funktionalität und Benutzererfahrung der gesamten Webanwendung aus der Perspektive des Endbenutzers testen. - White-Box-Testing: Beschreibung: White-Box-Testing, auch als Strukturtest bekannt, überprüft die interne Struktur, den Code und die Implementierung der Software. Tester benötigen detaillierte Kenntnisse des Codes. Vorteile:
- Hohe Testabdeckung, da interner Code überprüft wird
- Effizient beim Identifizieren von logischen Fehlern und Schwachstellen
- Hilft beim Optimieren und Refactoring des Codes
Nachteile: - Erfordert technisches Wissen und Zugriff auf den Quellcode
- Kann zeitaufwendig sein
- Keine Überprüfung der funktionalen Anforderungen
Verwendung: White-Box-Tests sind ideal für Unit-Tests und Integrationstests, da sie überprüfen, ob einzelne Komponenten und deren Integration korrekt funktionieren. - Graue-Box-Testing: Beschreibung: Graue-Box-Testing kombiniert Elemente von Black-Box und White-Box Testing. Tester haben eingeschränktes Wissen über die interne Struktur, was es ermöglicht, sowohl funktionale als auch strukturelle Aspekte der Software zu überprüfen. Vorteile:
- Balanciert die Vorteile von Black-Box- und White-Box-Tests
- Kann tiefere Tests durchführen als reine Black-Box-Tests
- Erlaubt effizienteres Testen durch kombinierte Techniken
Nachteile: - Kann komplex zu implementieren sein
- Nicht so umfassend wie vollständige White-Box-Tests
Verwendung: Graue-Box-Tests sind nützlich für detailliertere System- und Integrationstests, bei denen ein gewisses Maß an Kenntnissen über die interne Struktur erforderlich ist, um gründlichere Tests durchzuführen, ohne zu tief in den Code einzutauchen.
Zusammenfassend lässt sich sagen, dass für die Webanwendung:
- Unit-Tests und Integrationstests primär White-Box-Techniken verwenden sollten, um sicherzustellen, dass der Code und die Komponenten intern korrekt funktionieren.
- Systemtests sollten Graue-Box-Techniken verwenden, um eine gründliche Untersuchung der integrierten Komponenten mit einigem Wissen über die interne Struktur zu ermöglichen.
- Akzeptanztests sollten Black-Box-Techniken verwenden, um die Anwendungsfunktionen aus der Sicht des Endbenutzers zu validieren.
c)
c) Beschreibe, wie Du mittels Code Coverage, Branch Coverage und Path Coverage die Testabdeckung messen würdest. Verwende ein einfaches Code-Beispiel und berechne die verschiedenen Abdeckungsgrade.
Lösung:
Um die Testabdeckung zu messen, können verschiedene Metriken wie Code Coverage, Branch Coverage und Path Coverage, verwendet werden. Jede Metrik bietet einen anderen Grad an Einblick in die getesteten Bereiche des Codes.
- Code Coverage (Anweisungsabdeckung): Beschreibung: Code Coverage misst den Anteil der ausgeführten Codezeilen während der Tests. Es zeigt an, welche Zeilen des Codes durch die Tests ausgeführt wurden und welche nicht. Berechnung: Code Coverage = (Anzahl der ausgeführten Anweisungen / Anzahl der gesamten Anweisungen) * 100
- Branch Coverage (Zweigabdeckung): Beschreibung: Branch Coverage misst den Anteil der ausgeführten Entscheidungszweige (z.B. if-else-Strukturen) während der Tests. Es zeigt an, ob jeder mögliche Abzweig von Entscheidungsstrukturen getestet wurde. Berechnung: Branch Coverage = (Anzahl der ausgeführten Zweige / Anzahl der gesamten Zweige) * 100
- Path Coverage (Pfadabdeckung): Beschreibung: Path Coverage misst den Anteil der ausgeführten Codepfade während der Tests. Es zeigt, ob alle möglichen Pfade durch den Code getestet wurden. Berechnung: Path Coverage = (Anzahl der ausgeführten Pfade / Anzahl der gesamten Pfade) * 100
Lass uns zur Veranschaulichung ein einfaches Code-Beispiel verwenden:
function calculateDiscount(price, isMember) { if (price > 100) { if (isMember) { return price * 0.8; } else { return price * 0.9; } } else { return price; } }
Nun berechnen wir die verschiedenen Abdeckungsgrade für diesen Code:
d)
d) Beschreibe den Einsatz von JUnit und Selenium im Rahmen von Unit-Tests und Systemtests für das Projekt. Erläutere, wie Continuous Integration in Deine Teststrategie integriert werden kann und welche Vorteile dies für die Qualitätssicherung der Webanwendung bietet. Zeige dies exemplarisch in Form einer Jenkins-Pipeline-Konfiguration.
Lösung:
Der Einsatz von JUnit und Selenium kann die Qualitätssicherung eines Softwareprojekts erheblich verbessern, indem sie verschiedene Typen von Tests effizient unterstützen. Hier ist eine Beschreibung, wie diese Tools in Unit-Tests und Systemtests verwendet werden können, sowie eine Erläuterung zur Integration von Continuous Integration (CI) in die Teststrategie.
- JUnit für Unit-Tests: Beschreibung: JUnit ist ein Framework zur Durchführung von Unit-Tests in Java. Es bietet Annotations und Assertions, die es Entwicklern ermöglichen, Testfälle einfach zu erstellen und zu verwalten. Einsatz: JUnit kann verwendet werden, um einzelne Methoden und Klassen in der Webanwendung zu testen. Zum Beispiel könnte ein JUnit-Test sicherstellen, dass eine Funktion zur Berechnung des Rabatts korrekt arbeitet und die erwarteten Ergebnisse liefert.
- Selenium für Systemtests: Beschreibung: Selenium ist ein Werkzeug zur Automatisierung von Browser-Aktionen. Es kann verwendet werden, um die Webanwendung in verschiedenen Browsern zu testen und zu überprüfen, ob sie wie erwartet funktioniert. Einsatz: Selenium kann verwendet werden, um End-to-End-Tests der gesamten Webanwendung durchzuführen, zum Beispiel einen vollständigen Bestellvorgang zu simulieren: von der Produktauswahl bis zur Bestellbestätigung.
Continuous Integration (CI) Integration: CI ist ein praxisnaher Ansatz, bei dem Code-Änderungen regelmäßig in einem zentralen Repository integriert und automatisch getestet werden. Jenkins ist ein beliebtes CI-Tool, das diesen Prozess automatisieren kann. Vorteile:
- Früherkennung von Fehlern: durch regelmäßige Tests bei jedem Commit.
- Automatisierung: reduziert den manuellen Testaufwand.
- Kontinuierliches Feedback: Entwickler können schnell auf Fehler reagieren.
- Verbesserte Qualität: durch konsistente und wiederholbare Testprozesse.
Jenkins-Pipeline-Konfiguration:
Hier ist ein Beispiel für eine Jenkins-Pipeline-Konfiguration, die JUnit- und Selenium-Tests integriert:
pipeline { agent any stages { stage('Checkout') { steps { git 'https://github.com/dein-repo/webanwendung.git' } } stage('Build') { steps { sh './gradlew build' } } stage('JUnit Test') { steps { sh './gradlew test' } post { always { junit 'build/test-results/**/*.xml' } } } stage('Selenium Test') { steps { sh './gradlew seleniumTest' } post { always { archiveArtifacts artifacts: 'build/reports/selenium/**/*.html', allowEmptyArchive: true } } } } stage('Deploy') { steps { sh './gradlew deploy' } } } post { success { echo 'Pipeline erfolgreich abgeschlossen!' } failure { echo 'Pipeline fehlgeschlagen.' } } }
Schritte in der Jenkins-Pipeline:
- Checkout: Der Code wird aus dem Git-Repository ausgecheckt.
- Build: Die Anwendung wird gebaut.
- JUnit Test: Unit-Tests werden ausgeführt und die Ergebnisse werden gesammelt.
- Selenium Test: Systemtests werden mit Selenium durchgeführt und die Ergebnisse archiviert.
- Deploy: Die Anwendung wird bereitgestellt (optional).
Durch diese Pipeline stellst Du sicher, dass jeder Code-Commit durch eine Reihe von automatisierten Tests läuft, was die Qualitätssicherung für die Webanwendung insgesamt verbessert.
Aufgabe 4)
Bei der Verwaltung und Steuerung von Prozessen und Threads in einem Betriebssystem geht es darum, die verschiedenen Zustände der Prozesse zu managen und die Kommunikation und Synchronisation zwischen ihnen zu gewährleisten. Ressourcenmanagement spielt hierbei ebenfalls eine entscheidende Rolle. Die Prozesszustände umfassen New, Ready, Running, Blocked und Terminated. Threads sind leichtgewichtige Prozesse, die sich den Speicher teilen. Multithreading ermöglicht die Verteilung von Aufgaben auf mehrere Threads, um die Effizienz zu erhöhen. Bekannte Scheduling-Algorithmen sind FCFS (First-Come, First-Served), SJF (Shortest Job First), Round Robin und Priority Scheduling. Prozesse kommunizieren über Pipes, Shared Memory und Message Queues. Zur Synchronisation dienen Mechanismen wie Mutexe, Semaphore und Monitore. Das Ressourcenmanagement umfasst die Verwaltung von CPU, Speicher und Ein-/Ausgabe-Geräten. Ein Deadlock-Zustand kann auftreten, wenn mehrere Prozesse aufeinander warten, ohne fortschreiten zu können. Die Bedingungen für Deadlocks sind Mutual Exclusion, Hold and Wait, No Preemption und Circular Wait. Methoden zur Deadlock-Prävention und -Auflösung sind ebenfalls relevant.
a)
Beschreibe die Zustände, die ein Prozess durchlaufen kann, und erläutere eine mögliche Ursache für den Übergang von einem Zustand in den anderen.
Lösung:
Ein Prozess durchläuft verschiedene Zustände, die typischerweise in einem Betriebssystem verwaltet werden. Diese Zustände und ihre Übergänge werden wie folgt beschrieben:
- New (Neu): Ein Prozess wird erstellt und befindet sich im Anfangszustand. Innerhalb dieses Zustands wird der Prozess initialisiert, indem alle erforderlichen Ressourcen wie Speicher und CPU-Zeit zugewiesen werden.
- Ready (Bereit): Der Prozess ist bereit zur Ausführung, wartet jedoch darauf, dass der Scheduler ihm CPU-Zeit zuteilt. Ein Übergang von New zu Ready erfolgt, wenn die Initialisierung des Prozesses abgeschlossen ist.
- Running (Laufend): Der Prozess wird aktuell von der CPU ausgeführt. Der Übergang von Ready zu Running erfolgt, wenn der Scheduler dem Prozess CPU-Zeit zuweist.
- Blocked (Gesperrt): Der Prozess wartet auf eine Ressource oder ein Ereignis (z.B. Ein-/Ausgabeoperationen). Ein Übergang von Running zu Blocked kann auftreten, wenn der Prozess auf eine Eingabe/Ausgabe-Operation wartet.
- Terminated (Beendet): Der Prozess hat seine Ausführung beendet und wird aus dem System entfernt. Der Übergang von Running zu Terminated erfolgt, wenn der Prozess seine Aufgaben abgeschlossen hat.
Ursachen für den Übergang zwischen Zuständen:
- Von New zu Ready: Dieser Übergang erfolgt nach der Initialisierung des Prozesses, wenn er bereit ist, ausgeführt zu werden.
- Von Ready zu Running: Der Scheduler wählt den Prozess aus und weist ihm CPU-Zeit zu.
- Von Running zu Blocked: Der Prozess führt eine Operation aus, die auf eine Eingabe/Ausgabe-Aktion wartet oder braucht eine andere Ressource, die gerade nicht verfügbar ist.
- Von Running zu Ready: Der Scheduler kann den laufenden Prozess unterbrechen (zum Beispiel aufgrund von Round-Robin Scheduling) und ihn wieder in die Warteschlange einfügen, um anderen Prozessen eine Chance zur Ausführung zu geben.
- Von Blocked zu Ready: Der Prozess erhält die benötigte Ressource oder das Ereignis, auf das er wartet, tritt ein, sodass er wieder bereit zur Ausführung ist.
- Von Running zu Terminated: Der Prozess hat seine Aufgaben vollständig abgeschlossen und wird nun beendet.
b)
Implementiere in Python ein einfaches Multithreading-Beispiel, bei dem zwei Threads jeweils eine Zählvariable inkrementieren. Verwende geeignete Mechanismen zur Synchronisation, damit keine Race Conditions auftreten können.
from threading import Thread, Lockcounter = 0lock = Lock()def increment_counter(): global counter for _ in range(1000): with lock: counter += 1thread1 = Thread(target=increment_counter)thread2 = Thread(target=increment_counter)thread1.start()thread2.start()thread1.join()thread2.join()print(f'Final counter value: {counter}')
Lösung:
Hier ist ein einfaches Python-Beispiel, das zeigt, wie man zwei Threads implementiert, die jeweils eine Zählvariable inkrementieren. Dabei wird ein Lock verwendet, um sicherzustellen, dass keine Race Conditions auftreten:
from threading import Thread, Lock# Anfangswert des Zählerscounter = 0# Lock-Objekt zur Synchronisationlock = Lock()def increment_counter(): global counter for _ in range(1000): # Mit dem Lock verhindern wir Race Conditions with lock: counter += 1# Erstellen der beiden Threadsthread1 = Thread(target=increment_counter)thread2 = Thread(target=increment_counter)# Starten der beiden Threadsthread1.start()thread2.start()# Warten bis beide Threads abgeschlossen sindthread1.join()thread2.join()# Ausgeben des finalen Wertes des Zählersprint(f'Final counter value: {counter}')
c)
Diskutiere die Unterschiede und Vor- und Nachteile der Scheduling-Algorithmen FCFS, SJF, Round Robin und Priority Scheduling im Zusammenhang mit der CPU-Verwaltung.
Lösung:
Unterschiede und Vor- und Nachteile der Scheduling-Algorithmen
Im Zusammenhang mit der CPU-Verwaltung gibt es mehrere Scheduling-Algorithmen, die jeweils ihre eigenen Vor- und Nachteile haben. Hier sind die Hauptunterschiede sowie die Vor- und Nachteile der gängigsten Algorithmen:
FCFS (First-Come, First-Served)
- Beschreibung: Prozesse werden in der Reihenfolge bearbeitet, in der sie in die Warteschlange eingetreten sind.
- Vorteile:
- Einfach zu implementieren und zu verstehen.
- Geeignet für Batch-Systeme, wo die Laufzeit keine große Rolle spielt.
- Nachteile:
- Kann zu langen Wartezeiten führen, wenn ein Prozess mit langer Laufzeit zuerst bearbeitet wird (Konvoi-Effekt).
- Keine Berücksichtigung der Priorität oder Dringlichkeit eines Prozesses.
SJF (Shortest Job First)
- Beschreibung: Prozesse mit der kürzesten geschätzten Laufzeit werden zuerst bearbeitet.
- Vorteile:
- Minimiert die durchschnittliche Wartezeit im System.
- Effizient bei kurzen Prozessen und gut geeignet für interaktive Systeme.
- Nachteile:
- Schwierigkeiten bei der genauen Abschätzung der Laufzeit eines Prozesses.
- Kann zu Starvation führen, wenn lange Prozesse dauerhaft verdrängt werden.
Round Robin
- Beschreibung: Jeder Prozess erhält eine feste Zeitscheibe (Quantum) und wird zyklisch bearbeitet. Nach Ablauf der Zeitscheibe wird der Prozess unterbrochen und der nächste Prozess wird ausgeführt.
- Vorteile:
- Fairness, da jeder Prozess gleich viel CPU-Zeit erhält.
- Gut geeignet für Zeitteilungs- und interaktive Systeme.
- Nachteile:
- Die Wahl eines ungeeigneten Zeitquantums kann zu ineffizienter CPU-Nutzung führen (zu kurz: hohe Kontextwechsel-Kosten; zu lang: schlechte Reaktionszeit).
- Durch viele Kontextwechsel kann die Performance beeinträchtigt werden.
Priority Scheduling
- Beschreibung: Jeder Prozess erhält eine Priorität und die Prozesse werden entsprechend ihrer Priorität bearbeitet. Höher priorisierte Prozesse werden bevorzugt.
- Vorteile:
- Bietet die Möglichkeit, wichtigen Prozessen Vorrang zu geben.
- Flexibel für verschiedene Systemanforderungen anpassbar.
- Nachteile:
- Kann zu Starvation von niedrig priorisierten Prozessen führen.
- Erfordert eine sorgfältige und gerechte Zuweisung von Prioritäten.
Zusammenfassend lässt sich sagen, dass jeder Scheduling-Algorithmus spezifische Vor- und Nachteile hat, die je nach Anwendungsfall und Systemanforderungen unterschiedlich relevant sein können. Eine sorgfältige Auswahl und Anpassung des Algorithmus ist daher entscheidend für die Effizienz und Fairness der CPU-Verwaltung.
d)
Eine Deadlock-Situation kann entstehen, wenn verschiedene Prozesse auf Ressourcen zugreifen müssen, die von anderen Prozessen gehalten werden. Angenommen, wir haben die Prozesse P1 und P2 und die Ressourcen R1 und R2.
- P1 hat R1 und braucht noch R2, um weiterarbeiten zu können.
- P2 hat R2 und braucht noch R1, um weiterarbeiten zu können.
Beschreibe die Bedingung für das Entstehen eines Deadlocks und erkläre Methoden zur Prävention und Auflösung, unter Einbeziehung mathematischer Modelle, falls relevant.
Lösung:
Eine Deadlock-Situation kann auftreten, wenn verschiedene Prozesse auf Ressourcen zugreifen müssen, die von anderen Prozessen gehalten werden. In Deinem Beispiel (P1 und P2 mit R1 und R2) ist dies der Fall, wenn:
- P1 hat R1 und benötigt R2, um weiterarbeiten zu können.
- P2 hat R2 und benötigt R1, um weiterarbeiten zu können.
Dies führt zu einem Zyklus, in dem keiner der beiden Prozesse fortschreiten kann.
Bedingungen für das Entstehen eines Deadlocks
Ein Deadlock kann auftreten, wenn folgende vier Bedingungen gleichzeitig erfüllt sind:
- Mutual Exclusion (Wechselseitiger Ausschluss): Eine Ressource kann zu einem bestimmten Zeitpunkt nur von einem einzigen Prozess genutzt werden.
- Hold and Wait (Halten und Warten): Ein Prozess, der bereits Ressourcen hält, kann zusätzliche Ressourcen anfordern und darauf warten, dass sie freigegeben werden.
- No Preemption (Keine Enteignung): Ressourcen können nur freiwillig von dem Prozess freigegeben werden, der sie hält.
- Circular Wait (Kreisförmiges Warten): Es existiert eine geschlossene Warteschlange, in der jeder Prozess auf eine Ressource wartet, die von einem anderen Prozess in der Kette gehalten wird.
Methoden zur Deadlock-Prävention
Um einen Deadlock zu verhindern, können verschiedene Strategien angewendet werden:
- Verletzung einer oder mehrerer Deadlock-Bedingungen:
- Wechselseitiger Ausschluss: Dies kann schwierig zu realisieren sein, da viele Ressourcen von Natur aus exklusiv sind.
- Halten und Warten: Erzwingen, dass Prozesse alle benötigten Ressourcen im Voraus anfordern. Wenn ein Prozess eine Ressource nicht sofort erhalten kann, muss er alle besitzten Ressourcen freigeben.
- Keine Enteignung: Implementierung einer Politik, bei der Ressourcen mit einer Art Preemption gesichert werden können (die Ressource wird dem aktuellen Halter entzogen).
- Kreisförmiges Warten: Eine globale Ordnung der Ressourcen festlegen und sicherstellen, dass jeder Prozess Ressourcen nur in dieser Reihenfolge anfordert.
- Banker-Algorithmus: Ein mathematisches Modell, das auf der Ideen beruht, dass Systeme in einen sicherer Zustand übergehen. Der Algorithmus prüft, ob die Ressourcenzuweisungen sicher sind und ob die Deadlock-Risiken minimiert sind, bevor zusätzliche Ressourcen gewährt werden.
Methoden zur Deadlock-Auflösung
Falls ein Deadlock bereits eingetreten ist, können folgende Methoden angewendet werden:
- Prozessabbruch: Einen oder mehrere Prozesse beenden, um den Deadlock zu lösen. Dies kann zu Datenverlusten oder inkonsistenten Zuständen führen.
- Ressourcenenenteignung: Ressourcen von einigen Prozessen zwangsweise wegnehmen und sie anderen Prozessen zuweisen, um den Zyklus zu durchbrechen.
- Deadlock-Erfassung: Überwachen der Systemzustände, um Deadlocks zu erkennen; spezielle Strategien werden dabei angewendet, um Prozesse und Ressourcen regelmäßig zu überprüfen.
Zusammenfassend sind Prävention und Auflösung von Deadlocks essentielle Elemente im Ressourcenmanagement eines Betriebssystems, um die Effizienz und Stabilität zu gewährleisten.