DIGITAL
Softwareengineering muss geübt werden.
Schreiben von Software bedarf ständiger Übung, vor allem die Entscheidungen, die Sie beim Design der Klassen (im Falle der OOP-Programmierung) und der nötigen Beziehungen dieser Klassen treffen, werden sich erst durch häufiges Üben festigen. Bevor wir uns also konkrete Softwaredesigns-Schemata anschauen soll Ihnen diese Aufgabe die Möglichkeit geben kreativ zu werden. Daazu soll auf diesem Übungsblatt eine Projektaufgabe gelöst werden.1 Das Ziel ist es dass jede Lerngruppe jeden Schritt von der Konzeption bis zum finalen Code gemeinsam löst. Sprechen Sie sich also mit den anderen Mitgliedern Ihrer Lerngruppe gut miteinander ab.
Die Aufgabe teilt sich in zwei Teile auf.
Der eine Teil ist der Planungsteil, der andere ist das praktische Projekt. Beide Teile sollen in der Gruppe gemeinsam gelöst werden. Bei der Planung geht es darum, die Ideen und Konzepte der Implementierung als UML-Diagramm zu visualisieren. Beim UML-Diagramm geht es darum die grobe Struktur und das Zusammenspiel der verschiedenen Klassen zu erklären. (Dazu gibt einen Anhang, in dem die Syntax von UML-Diagraamen mithilfe von tikz-uml
erklärt wird.) Im Praxisteil soll dieser abstrakte Plan als Code implementiert werden.
Das Projekt selbst erstreckt sich über zwei Wochen.
In der ersten Woche wird das Grundsystem gebaut und das passende UML-Diagramm dazu formuliert. In der zweiten Woche soll basierend auf dem Code der ersten Woche eine Erweiterung eingebaut werden. Beachten Sie bei der Bearbeitung des Basissystems, dass Teile ihres Codes austauschbar sind (Stichwort Polymorphie des letzten Übungsblattes). Überlegen Sie sich in der Gruppe welche Teile dies betreffen könnten. Eine einfache Erweiterung wird bereits auf diesem Blatt gefordert, damit Sie sehen was damit gemeint sein könnte.
Wichtig: Schauen Sie sich nicht die Erweiterung an, bevor Sie mit dem Basissystem fertig sind, um einzuschätzen, ob Sie ähnliche Arten von Erweiterung auf dem nächsten Blatt einbauen können. Falls Sie schummeln, ist das Ziel der Übung dahin. Aus dem Grund halten wir aber einige Erweiterungen auf diesem Blatt zurück und zeigen Sie Ihnen erst nächste Woche.
Ziel dieser Übung
Neben der Planung und der Möglichkeit, eine Aufgabe kreativ zu lösen, bringt Softwareengineering das typische Problem mit sich, dass man vorher nicht weiß was man später benötigen wird bzw. in welche Richtung sich ein Projekt entwickeln wird. Aus dem Grund soll das Ganze hier geübt werden und getestet werden, wie gut das ganze funktioniert. Diese Schwierigkeit zu erkennen und dann eventuell mehr oder weniger Aufwand beim Implementieren der Erweiterung in der nächsten Woche zu haben ist Teil der Übung. Machen Sie sich bewusst welche Klassen nötig sind und ob eine Erweiterung einer Klasse in Ihrem Code möglich oder sinnvoll ist. Anfänger-OOP-Designs tendieren häufig zum globalen Denken: unnötige globale Variablen, unnötige Zeiger und unangemessene Abhängigkeiten von Implementierungsdetails.2 Das Ziel in dieser Aufgabe ist es explizit OOP-Klassendesign zu üben. Und vor allem: Die Konzeption selbst auszuprobieren.
[1] Im letzten Jahr war eine solche größere Kreativaufgabe ein Ausdrücklicher wunsch einiger Studierender.
[2] Das soll nicht bedeuten, dass OOP der Weißheit letzter Schluss ist; häufig bezahlt man Austauschbarkeit mit Performanceeinbußungen und unüberschaubaren Klassenhierarchien. Ein Beispiel für das andere Extrem, also zu viel OOP, kann etwa hier (leider Java statt C++) angeschaut werden.
Letzte Änderung: 15. June 2020, 13:54 Uhr
Änderungshistorie:
Sobald man mit einer Programmiersprache über for
-Loops zu der Definition von Klassen gekommen ist, ist es durchaus eine gute Übung, ein kleines Spiel zu implementieren. Natürlich wäre das Ganze mit GUIs und der Möglichkeit zu zeichnen sehr viel interessanter, aber leider sind wir noch nicht so weit. Aus dem Grund schreiben wir eine kleine Simulation, die uns direkt auf der Konsole ausgegeben werden soll. Ein Vorteil einer Simulation gegenüber eineem interessanten Spiel ist, dass dynamische Tastenabfrage in der Konsole leider auch schwierig zu bewerkstelligen ist.
Der Hauptgrund für eine Simulation als Aufgabe ist, dass hierbei verschiedene Akteure selbstständdig auf einander reagieren. Diese Eigenschaft macht eine solche Simulation zu einem ausgezeichneten Kandidaten für eine OOP-Aufgabe.
Es gibt zwei Projekte zur Auswahl. Wählen Sie als Gruppe eines der beiden Projekte aus und bearbeiten Sie dann die Aufgaben.
Wählen Sie als erstes gemeinsam im Team eines der beiden Projekte aus und besprechen Sie neben dem internen Interesse auch eventuelle Pro- und Kontra-Argumente der jeweiligen dahinterliegenden Aufgaben. Überlegen Sie sich schon einmal wie das Projekt gemeinsam gelöst werden kann. Es geht hier um Softwareengineering. Aufgabenverteilung, Planung und eine Verständigung innerhalb der Gruppe kann wichtig werden.
Lesen Sie vor der internen Besprechung die Anlage für Klassendiagramme und schauen Sie sich noch einmal intensiv die UML-Beispiele der Vorlesung an.
Überlegen Sie sich gemeinsam, welche Klassen Sie innerhalb Ihres Programmes verwenden werden müssten und welche Methode diese jeweils bereitstellen sollten. In der OOP gibt es zwei Ansätze, die dabei gefahren werden können:
class Simulation
, darin ist eine Methode simulate
) und sich langsam immer mehr zu den spezielleren Klassen (etwa class Car
) vorarbeiten.Beide Herangehensweisen bringen so ihre Vor- und Nachteile mit sich. Meiner persönlichen Erfahrung nach muss je nach Projekt abgewogen werden; Während das erstere zwar oft schneller zu einer schönen API führt, kann es schnell passieren, dass die gewünschten Pläne nicht so leicht umzusetzen sind und große Teile umgeschrieben werden müssen. Andererseits ist letzteres vielleicht näher am üblichen „direkt darauf los programmieren“, kann jedoch auch schnell zu globalem & prozeduralem Code führen der nicht so leicht erweiterbar ist und daher ebenfalls große Teile neu geschrieben werden müssen.
Dies einfach auszuprobieren und nach dem Bauchgefühl zu entscheiden ist Teil der Übung. ;)
Punkte gibt es für
Geben Sie das fertige Diagramm in ihrem Repository ab.
(Wie vorher auch, ist es natürlich nicht zwingend erforderlich tikz-uml
zu verwenden.)
main
-Methode anzufangen. Arbeiten Sie sich dann „von oben“ durch alle nötigen Programmebenen durch.
Implementieren Sie die von Ihnen ausgewählte Problemstellung.
Achten Sie bei der Abgabe darauf
Dies könnte für eine (langsamere) Visualisierung auch nützlich sein.
Programm anhalten: Quelle
#include <iostream>
#include <chrono>
#include <thread>
int main() {
using namespace std::chrono_literals;
std::cout << "Hello waiter\n" << std::flush;
std::this_thread::sleep_for(2s);
std::cout << "Waited\n";
}