-
Notifications
You must be signed in to change notification settings - Fork 0
Design Dokumentation
Bei der Planung und Implementierung des Projekts wurde darauf geachtet das durch eine lose Kopplung die Arbeitsteilung und Erweiterung gewährleistet wird. Die Gliederung erfolgte durch eine Zusammenfassung von Assemblies zu logischen Komponenten. Die Zuordnung erfolgt hier über den Namespace.
Die folgenden Design-Entscheidungen und -Vorgaben wurden aus dieser Architektur abgeleitet.

Folgende Design-Entscheidungen wurden zu Anfang getroffen:
- Verwendung von WCF Named Pipes um die logischen Komponenten miteinander zu verbinden.
- Pro logischer Komponente muss es eine Assembly geben, welche die Funktionen und Objekte bereitstellt, welche über die WCF angeboten werden.
- Eine zentrale Logging-Komponente wird verwendet um eine gute Sichtbarkeit über die Events der gesamten Applikation zu gewährleisten.
- Die Simulations-Komponenten sollen unabhängig vom UI laufen können. Dies wurde entschieden um die Austauschbarkeit des UI's zu ermöglichen.
Um das zentrale Logging zu ermöglichen wird das Framework Nlog (http://nlog-project.org/) eingesetzt. Dieses wird so eingesetzt das die abgesetzten Logs per UDP an 127.0.0.1:9999 gesendet werden. Diese Konfiguration erlaubt es sehr einfach ein remote Logging einzurichten in dem eine neue IP-Addresse konfiguriert wird. Als Logviewer und, in unserem Fall, auch Logserver wurde Sentinel (https://sentinel.codeplex.com/) verwendet. Dieses Tool erlaubt es die Log-Nachrichten zu filtern und bringt auch ein geeignetes User-Interface mit. Die Debugging- Arbeiten während der Entwicklung können damit im vollen Ausmaß abgedeckt werden.
Um Logging in einer Klasse zu ermöglichen ist es nötig eine Nlog.config im Assembly mit passendem Target pro Assembly zu haben. In der Klasse kann dann mit dem Aufruf
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
Ein Logging-Objekt erstellt werden. Die Verwendung sieht dann folgendermaßen aus
Logger.Trace("Starting Simulation");
Die Simulations-Komponente beinhaltet den Kern der Simulation. Alle Kopplungspunkte werden über folgendes Assembly angeboten und entgegen genommen.
TrafficSimulation.Simulation.WebService
Die Definition von Objekten und Funktionen werden in einem eigenem "Contracts" Assembly definiert. Es werden sogenannte DataContracts und OperationContracts definiert. Diese definieren die angebotene Schnittstelle der Simulationskomponente, welche von anderen Komponenten über das Windows Communication Foundation (WCF) Framework erreichbar ist.
Das Assembly TrafficSimulation.Simulation.Contracts beinhaltet die Schnittstellen-Definitionen für die Simulationskomponente.
Dazu wurden Objekte definiert, welche die ausgetauschten Daten repräsentieren, und Methoden definiert welche Funktionalität nach außen bringen.

Das Interface ISimulationService, welches die Definitionen der Methoden beinhaltet, wird in der Assembly TrafficSimulation.Simulation.Webservice implementiert.
Die Engine ist der Kern der Simulation. Die Simulation hat einen "Tick" als kleinste Zeiteinheit. Wird eine Simulation durchgeführt ist dies aus Sicht der Engine eine abfolge von Ticks. Jedes Simulations-Objekt hat eine Methode über die es "Tickable" wird. Es wird also pro Tick in der Simulation jedes Objekt über diese Methode aufgerufen. Dies ermöglicht eine atomare Simulation.
Auszug Klassendiagramm SimulationEngine:

Dieses Assembly stellt die Schnittstelle nach außen auf Komponenten-Ebene dar.

Diese Komponente übernimmt die Steuerung der Ampeln in der Simulation. Die Simulations-Komponente bietet dazu passende Funktionen über WCF an. Die Ampeln können über eine ID der Kreuzung zugeordnet werden und haben Informationen zu der Position innerhalb der Kreuzung.
Dieses Assembly definiert wie in den anderen Komponenten die Schnittstellendefiniton der TrafficLightControl Komponente. Im Webservice Assembly werden diese wiederum implementiert. Folgende Funktionalitäten werden nach außen bereitgestellt
- Start TrafficLightControl
- Stop TrafficLightControl
- Step (einen Tick der Simulation durchführen)
- SetLightRed
- SetLightGreen
- ResetInterval
In diesem Teil der Komponente wird die Logik zur Ampelsteuerung umgesetzt. Also die detailierten zeitlichen Abläufe der Schaltvorgänge passend zu der Position der Ampel.
Das User-Interface ist so designt, dass es sich zur Simulations-Komponente verbindet und dort aktuelle Zustände der Simulation abfragt. Über das Userinterface können aber dennoch Aktionen in der Simulation ausgelöst werden, so wie Start, Pause, Einzeltick, Ampel-Schaltung und Fahrzeuge als defekt makieren.
In diesem Assembly ist das UI definiert und das zugrundeliegende View Model. Das View Model bindet über WCF die benötigten Funktionen der anderen Komponenten ein.

Der Aufruf des Fensters und die Initialisierung der benötigten Verbindungen zur Simulations-Komponente erfolgt in der Bootstrapper Klasse.
Zum Zeichnen des Fensters wurde die Prism Library (https://github.com/PrismLibrary/Prism) verwendet. Diese erlaubt es einfache xaml Frontends zu erstellen und wurde gewählt um die Lernkurve flach zu halten, und schneller ein laufendes UI erstellen zu können.
Folgender Screenshot zeigt das UI welches auf diesem Weg erstellt worden ist.
Eine Anforderung die sich im laufe der Erstellung des Projekts ergab war Debugging Informationen über das UI ausgeben zu können. Folgende Ansicht der Fahrzeuge konnte dies abdecken.
Laut Aufgabenstellung soll die Simulation aus Visual Studio heraus startbar sein. Dazu wurde im Assembly TrafficSimulation.Simulation.Application eine Klasse implementiert die alle Teile der Lösung startet.
Die Klasse Program startet folgende Prozesse.
- Logging-Controller (nlog)
- Simulations-Komponente
- Traffic-Light-Control-Komponente
- UI-Komponente
- Sentinel
Die Simulation startet dann mit der ersten Verbindung des UI zu der Simulations-Komponente.