Separation of Concerns
Das Repository separation-of-concerns beinhaltet drei Beispiele mit je drei Quellcodedateien:
*.ts: Die Programmbibliothek mit jeweils einer Funktion, welche die eigentliche Logik enthält.*_main.ts: Ein Demoprogramm, welches die jeweilige Funktion aufruft.*_test.ts: Ein Dummy-Testfall als Vorlage.
Auftrag
- Erstelle einen Fork vom Repository und klone diesen.
- Suche dir eine der nachfolgend beschriebenen Aufgaben aus. Du kannst in beliebiger Reihenfolge vorgehen.
- Gehe für jede Aufgabe nach den folgenden Schritten vor:
- Testen Sie den jeweiligen Beispielcode mit verschiedenen Argumenten, indem du das Beispielprogramm ausführst. (Befolge hierzu die Anweisungen in
README.mddes Repositories.) - Betrachte den Code zur jeweiligen Aufgabe. Überlege dir, welche verschiedenen Aspekte in der einen grossen Methode gemeinsam behandelt werden. (Tipp: Oft werden “Berechnung” und “Ausgabe” vermischt. Es gibt aber noch weitere Aspekte, die man separieren könnte.)
- Nimm ein Refactoring am Code vor, um eine bessere Separation of Concerns zu erreichen. Passe wenn nötig den aufrufenden Code im Demoprogramm an, um den Beispielcode wieder laufen lassen zu können.
- Dank der verbesserten Separation of Concerns sollte sich der Code besser automatisiert testen lassen. Schreibe Komponententests für den überarbeiteten Code. (Entscheide selber, welche und wie viele.)
- Testen Sie den jeweiligen Beispielcode mit verschiedenen Argumenten, indem du das Beispielprogramm ausführst. (Befolge hierzu die Anweisungen in
- Wiederholen Sie dieses Vorgehen für die nächste Aufgabe.
Die einzelnen Aufgaben werden in den folgenden Abschnitten erklärt.
Multiplikationstabelle
Die Funktion printMultiplicationTable in multiplication_table.ts gibt eine Multiplikationstabelle für die Zahlen des Array-Parameters aus. Es wird eine Matrix ausgegeben, bei der jede Zahl als Spalte und Zeile vorkommt. Für jede Spalten- und Zeilenkombination wird das Produkt berechnet und in der jeweiligen Zelle ausgegeben.
Die Ausgabe mit der korrekten Spaltenbreite ist dabei recht ausgeklügelt. Weniger gut gelöst ist die Organisation des Codes. Verbessere diese.
Primfaktorzerlegung
Bei der Primfaktorzerlegung wird eine Zahl in ihre Primfaktoren zerteilt. Man beginnt mit der kleinsten Primzahl 2 und versucht die gegebene Zahl dadurch zu teilen. Ist eine Teilung möglich, wird wiederum versucht den Rest durch die gleiche Primzahl zu teilen. Ist die Teilung nicht restlos möglich, wird mit der nächsten Primzahl fortgefahren. Die Faktoren, mit denen die Teilung restlos funktioniert hat, werden dabei aufgelistet. Multipliziert man diese Faktoren anschliessend, kommt man wieder auf die Originalzahl.
Beispiele für Primfaktorzerlegungen:
| Zahl | Primfaktoren | Kontrolle |
|---|---|---|
| 10 | 2, 5 | 2 * 5 = 10 |
| 42 | 2, 3, 7 | 2 * 3 * 7 = 42 |
| 55 | 5, 11 | 5 * 11 = 55 |
| 99 | 3, 3, 11 | 3 * 3 * 11 = 99 |
| 1024 | 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 | 2^10 = 1024 |
Die Primfaktorenzerlegung wird z.B. bei der Kryptographie (genauer: der Kryptoanalyse) verwendet, um beispielsweise RSA-Schlüssel zu knacken. (Hierbei kommen jedoch sehr grosse Zahlen zum Einsatz.)
Für die Primfaktorzerlegung müssen zunächst die Primzahlen bis zu einer gegebenen Zahl gefunden werden. Dies könnte auch wesentlich effizienter implementiert werden. Versuchen Sie eine Primfaktorzerlegung einer grösseren Zahl, sodass es spürbar langsam läuft. Verbessern Sie anschliessend die Performance, bis das Programm wieder schnell genug läuft (Ideen: Caching oder das Sieb des Eratosthenes).
Die Funktion factor in prime_factors.ts erwartet ein Array von zu faktorisierenden positiven Zahlen. Verbessere diese Funktion.
Monty-Hall-Problem
In der Spielshow Monty Hall bekommen die Teilnehmer drei Tore zur Auswahl: Hinter einem verbirgt sich der Hauptgewinn von einem Auto, hinter den anderen beiden eine Ziege als Niete/Trostpreis.
Nachdem der Spieler sich für ein Tor entscheidet, lässt Monty Hall jeweils ein anderes Tor öffnen, hinter welchem sich eine Ziege verbirgt. Der Spieler hat nun die Möglichkeit seine Wahl zu ändern oder bei der ursprünglichen Wahl zu bleiben.
Das Monty-Hall-Problem lautet folgendermassen:
Verbessern sich durch das Wechseln der Wahl die Gewinnchancen?
Im gegebenen Code wird versucht, die Frage mittels einer Simulation zu lösen. Hierbei wird eine gegebene Anzahl von Spielen gespielt. Dabei wird ausgerechnet, wie oft der Spieler gewinnen würde wenn er:
- bei seiner Wahl bleibt
- seine Wahl ändert
Das Ergebnis ist verblüffend. Weniger beeindruckend (und schwerer testbar) ist jedoch die Implementierung der Funktion play in monty_hall.ts.