In der Mai-Ausgabe der dotnetpro war die Dojo-Aufgabe (mehr Infos zu den Dojo-Aufgaben) eine verkettete Liste zu implementieren. Eine Aufgabe, bei der keine Ressourcenzugriffe (Datenbank, Filesystem …) und keine Abhängigkeiten das Testen erschweren. Also ein ideales Tummelfeld, um Unit Tests zu verwenden und dabei Visual T# einzusetzen (Einstieg in Visual T#). Dabei versuche ich nach dem Test-First Prinzip vorzugehen.
Aller Anfang ist leicht
Die Aufgabenstellung beschreibt die Anforderungen und die „Architektur“ der Liste schon relativ präzise, so dass ich mir erlaube gleich Visual Studio zu starten, ohne erst eine Skizze zu Papier zu bringen.
Die Visual Studio Solution enthält keine Überraschungen. Als erstes Project die Klassenbibliothek mit der zu erstellenden verketteten Liste (LinkedList) und als zweites das Visual T# Testprojekt.
Als erstes erfüllen wir die Anforderung, dass unsere LinkedList das Interface IList<T> implementiert. Die Methodenrümpfe erstellt uns Visual Studio auf Mausklick, so dass unser Projekt bereit für die ersten Test-Implementationen ist.
Erster Test
Als ersten Test erstellen wir die Überprüfung, dass eine leere Liste beim Abfragen der Anzahl der Elemente null zurück gibt.
GeSHi Error: GeSHi could not find the language tsharp (using path /home/rolandba/public_html/blog/wp-content/plugins/codecolorer/lib/geshi/) (code 2)
Die einfachste Implementierung, die diesen Test erfüllt sieht so aus:
1 2 3 4 | public int Count { get { return 0; } } |
Noch nicht wirklich eine sinnvolle Implementierung aber aus dem Test-First Ansatz bzw. dem YAGNI-Prinzip richtig.
Ein Fuss vor den Andern
Für den nächsten Schritt müssen wir etwas mehr investieren. Wenn wir ein Element in der Liste haben möchten müssen wir zuerst das Element hinzufügen.
GeSHi Error: GeSHi could not find the language tsharp (using path /home/rolandba/public_html/blog/wp-content/plugins/codecolorer/lib/geshi/) (code 2)
Da wir noch keine Implementation für Add() haben wirft dieser Test eine NotImplementedException. Fügen wir also die Implementation hinzu und bauen auch das Property Count so um, dass der Test erfogreich ist. Dabei implementieren wir (vielleicht ein bisschen entgegen dem YAGNI- und KISS-Prinzip) auch gleich den internen Container, da dieser ja als Anforderung verlangt wird.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | public class LinkedList< T > : IList< T > { private class LinkedListElement { public T Element { get; set; } public LinkedListElement Next { get; set; } } (...) public void Add(T item) { first = new LinkedListElement() { Element = item }; } public int Count { get { if (first == null) return 0; return 1; } } (...) private LinkedListElement first; } |
Dieser Code erfüllt die in den Tests definierten Anforderungen, aber da fehlt noch einiges. Machen wir also den nächsten Schritt, noch ein Element hinzufügen und die Anzahl überprüfen.
GeSHi Error: GeSHi could not find the language tsharp (using path /home/rolandba/public_html/blog/wp-content/plugins/codecolorer/lib/geshi/) (code 2)
Kleine Anmerkung zu den Tests: Auch wenn es vielleicht den Anschein macht, ich habe keine Tests geändert sondern neue hinzugefügt. Bei T# dürfen mehrere Tests die selbe Signatur (in diesem Fall ‚test Count get‘) haben, das Testprojekt enthält jetzt also drei Tests.
Unbegrenztes Wachstum
Nun ist es Zeit, bei Add() und Count eine allgemeine Implementation einzufügen, die für beliebig viele (im Rahmen der Schnittstelle, Count ist z.B. vom Typ int) Elemente funktioniert.
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 | public void Add(T item) { if (first == null) { first = new LinkedListElement() { Element = item }; } else { LinkedListElement temp = first; while(temp.Next != null) { temp = temp.Next; } temp.Next = new LinkedListElement { Element = item }; } } public int Count { get { if (first == null) return 0; int count = 1; LinkedListElement temp = first; while (temp.Next != null) { temp = temp.Next; count++; } return count; } } |
Vertrauen ist gut, Kontrolle ist besser
Mit einem weiteren Test überprüfen wir die allgemeine Gültigkeit der Implementation.
GeSHi Error: GeSHi could not find the language tsharp (using path /home/rolandba/public_html/blog/wp-content/plugins/codecolorer/lib/geshi/) (code 2)
Somit haben wir einen Stand erreicht, bei dem wir die Liste befüllen können und die Werte scheinbar auch gespeichert werden. Um dies aber überprüfen zu können müssen wir eine Möglichkeit implementieren, auf die gespeicherten Werte wieder zugreifen zu können. Diese Funktionalität werden wir im zweiten Teil realisieren.
Pingback: LinkedList Dojo mit Visual T# – Teil 2 « of bits and bytes
Pingback: IList Dojo Retrospektive « of bits and bytes