Tag-Archive for » C# «

Let’s play tennis, with TDD

TDD & Code Kata’s

Now I’m working since more than four months as a software engineer at bbv Software Services in Switzerland. Every new employee at bbv needs to attend several courses (bbv Academy) to improve and extend his skills towards a good software developer. After my Scrum Master course, the next one on my schedule was Test Driven Development.

In addition to the theory why TDD, clean code and pair programming is highly desirable the course was accompanied with hands-on code kata’s. For those who don’t know what a code kata is, here is a citation from Wikipedia:

A code kata is an exercise in programming which helps a programmer hone their skills through practice and repetition.

One kata of the course was the Tennis Scorer. The goal was to implement a mechanism, which prints the score of a single game (therefore there are no sets).

Our Referee

The rules given were the following:

  1. A game is won by the first player to have won at least four points in total and at least two points more than the opponent.
  2. The running score of each game is described in a manner peculiar to tennis: scores from zero to three points are described as “love”, “fifteen”, “thirty”, and “forty” respectively.
  3. If at least three points have been scored by each player, and the scores are equal, the score is “deuce”.
  4. If at least three points have been scored by each side and a player has one more point than his opponent, the score of the game is “advantage” for the player in the lead.

Our implementation should be based on the ITennisScorer interface, which of yourse was changed during the exercise.

</span>
<pre>namespace Tennis
{
    public interface ITennisScorer
    {
        void AchievesScore(Player player);

        string GameScore { get; }
    }

    public enum Player
    {
        PlayerA,
        PlayerB
    }
}

Because it was a TDD course, we needed to build up a TODO list of appropriate unit tests first (e.g. Game just started, no one scored so far, expected score “love”).

Then we implented the unit tests one by one. Each of them had to fail first. Then came the actual implementation, test should pass afterwards. Code Refactoring -> All tests should pass.

Our Players

My initial implementation was blotched with many if statements, handling all the special cases for the game score (deuce, advantage, …). I also had code duplication, because I needed to track and update the score of player A and B separately.

But here comes the ultimate advantage of TDD. You’re not afraid anymore to refactor your code to a better architecture and solution. Because you know you can (and should) always run your unit tests and see if everything is still behaving as desired. You can sleep comfortably without to fear the next morning from an upcoming design change. Ok, I know. Some can still sleep during the nights without TDD, but they will be haunted by bad dreams 😉

So I refactored my code and eliminated the code duplication. Instead of using an enum to track the actual player score, I simply use a two-dimensional array, which holds all the possible scores of a game.

namespace Tennis
{
    public class TennisScorer : ITennisScorer
    {
        private int scoreA;
        private int scoreB;

        private const string GameA = "gameA";
        private const string GameB = "gameB";
        private const string AdvantageA = "advantageA";
        private const string AdvantageB = "advantageB";

        private static readonly string[][] PlayerScores = new[]
            {
                new[] {"love",  "15:0",     "30:0",     "40:0",     GameA},
                new[] {"0:15",  "15:15",    "30:15",    "40:15",    GameA},
                new[] {"0:30",  "15:30",    "30:30",    "40:30",    GameA},
                new[] {"0:40",  "15:40",    "30:40",    "deuce",    AdvantageA},
                new[] { GameB,   GameB,     GameB,      AdvantageB}
            };

        public void AchievesScore(Player player)
        {
            switch (player)
            {
                case Player.PlayerA:
                    UpdateGameScore(ref scoreA, ref scoreB);
                    break;
                case Player.PlayerB:
                    UpdateGameScore(ref scoreB, ref scoreA);
                    break;
            }
        }

        public string GameScore
        {
            get { return PlayerScores[scoreB][scoreA]; }
        }

        private void UpdateGameScore(ref int playerToAddScore, ref int opponentScore)
        {
            if (GameScore == AdvantageA || GameScore == AdvantageB)
            {
                opponentScore--;
            }
            else if (GameScore != GameA && GameScore != GameB)
            {
                playerToAddScore++;
            }
        }
    }
}

The Regulating Authority

I also refactored my unit tests. There were many tests, testing all the possible game processes. But my course instructor gave me the hint to use Nunit’s RowTest. Instead of writing many, almost identical tests for each case, I wrote just one parametrized unit test and the many case were provided as a parameter.

namespace Tennis.Test
{
    using NUnit.Framework;
    using FluentAssertions;

    [TestFixture]
    public class TennisScorerTest
    {
        private TennisScorer testee;

        [SetUp]
        public void SetUp()
        {
            testee = new TennisScorer();
        }

        [TestCase("", "love")]
        [TestCase("A", "15:0")]
        [TestCase("AAB", "30:15")]
        [TestCase("AAAB", "40:15")]
        [TestCase("BBB", "0:40")]
        [TestCase("BBB", "0:40")]
        [TestCase("ABABAB", "deuce")]
        [TestCase("AAABBB", "deuce")]
        [TestCase("AABBAB", "deuce")]
        [TestCase("AAABBBA", "advantageA")]
        [TestCase("AAABBBB", "advantageB")]
        [TestCase("AAAA", "gameA")]
        [TestCase("AAAAA", "gameA")]
        [TestCase("AAAABBBBBB", "gameA")]
        [TestCase("AAABBBBB", "gameB")]
        [TestCase("ABABABABABABABABABABABAA", "gameA")]
        public void PlayerScores(string game, string expectedScores)
        {
            foreach (var currentScore in game)
            {
                switch (currentScore)
                {
                    case 'A':
                        testee.AchievesScore(Player.PlayerA);
                        break;
                    case 'B':
                        testee.AchievesScore(Player.PlayerB);
                        break;
                }
            }
            testee.GameScore.Should().Be(expectedScores);
        }
    }
}

References & Coaches

If you want to practice your programming skills, I can encourage you to do some code kata’s, or similar challenges, to stay fresh in your head.

Here is a list of some useful sites with some brain-teasers and, if given, their solutions:

My Tennis Scorer implementation is available on GitHub.

Category: C#, Coding  Tags: , ,  One Comment

1km Notenstatistik

Jedes Semester werden die Noten anonymisiert von der HSLU T&A veröffentlicht. Einige Stunden später erscheint auf der 1km Seite auch die entsprechende Notenstatistik.
In der Statistik ist die prozentuale Verteilung der Noten für die Module ersichtlich. Zudem kann jeder Student seine Noten über die persönliche Matrikelnummer abfragen.
Die veröffentlichten Noten wurden bisher in einem aufwendigen Verfahren manuell konvertiert um sie in die Datenbank der Webseite abzufüllen. MS Word & Excel sowie Regex Befehle im Texteditor waren für die Konvertierung notwendig. Der Aufwand belief sich für jedes Semester zwischen 1-3 Stunden.

Nun habe ich ein kleines C# Programm geschrieben, welches die Noten aus der veröffentlichten PDF Datei einliest, diese konvertiert und anschliessend in einem geeigneten Format für das PHP Skript der Webseite abspeichert.

Folgende Features weist das Programm auf:

  • Modularer Code (Strategy und Factory Pattern)
  • Die einzelnen Tasks sind zur Laufzeit austauschbar
  • Tasks werden in Threads abgearbeitet
  • Nutzung von eigenen Events und Eventargumenten um über den Fortschritt der Tasks zu benachrichtigen
  • itextsharp Bibliothek um PDF Datei einzulesen
  • Speicherung der Applikationseinstellungen in Properties
  • Nutzung von ILMerge um alle Abhängigkeiten in eine EXE Datei zu packen

Das C# Projekt gibt es hier.

Notenparser in C#

Notenparser in C#

Category: C#  Tags:  One Comment