Sergey Shishkin

on agile software development

Coding Dojo @ .NET User Group Rhine/Ruhr

Last month we had a coding dojo on a user group meeting in Ratingen. This was the first coding dojo for most of the user group members and I was allowed to facilitate it. As a big fan of Ilker’s style coding dojos for his entertaining talent I wanted to deliver an energizing experience to the attendees if anything at all. So instead of throwing people at kata right away and watching them arguing which unit-testing framework to use I decided make a “demo of a coding dojo”.

Imagine yourself sitting in a racing car having never seen a race and knowing only how to ride a bicycle. Now go on and have fun on a track. Two hours later you already can start the engine and release the handbrake.  Was it fun? Will you come next time to learn how to shift gears? I doubt. Now Imagine somebody took you for a drifty ride. Now it makes sense! Now there is even a point to learn it yourself. The same way I learned to love coding katas: by watching masters (like this one) doing them.

I choose a modified version of the String Calculator Kata: instead of just adding numbers joined to a string, I aimed to implement an arithmetic expression evaluator (“1 + 2” –> 3). My tools for this kata included VS2010, C#, Resharper, xunit.net as testing framework, and Should as a fluent assertions library.

The thing I like most about TDD is that the whole software design emerges out of a consequence of simple decisions. Each design is unique and none is the right one. You can follow my implementation on Github, I’ll just list here most noticeable steps:

The first feature was to evaluate a decimal constant. The simple “double.Parse(expression)” method did the trick.

The next one was a simple addition. The “string.Split(‘+’)” is obvious to extract the arguments of addition, the next step is however that same little design decision that defined the whole solution. Instead of manually juggling array indices I used my favorite .NET API – Linq. So, to add the arguments from a string array I wrote the following:

return expression

    .Split('+')

    .Select(x => double.Parse(x))

    .Aggregate((a, b) => a + b);

Now implementing multiplication was analogous. The resulting code duplication was an obvious smell though. I always forget those fancy functional slang, but the point was to effectively build a pipeline of functions, where each function is applied to the result of the next one in the pipeline. Then the only thing to do is to call that pipeline as a function and pass it the original string expression. The whole solution looks like this:

public class Calculator

{

    private static readonly Func<string, double> Parse = double.Parse;

    private static readonly Func<string, double> Pipeline = Parse

        .Wrap(‘*’, (a, b) => a*b)

        .Wrap(‘/’, (a, b) => a/b)

        .Wrap(‘+’, (a, b) => a + b)

        .Wrap(‘-‘, (a, b) => a – b)

        ;

    public double Evaluate(string expression)

    {

        return Pipeline(expression);

    }

}

public static class PipelineExtensions

{

    public static Func<string, double> Wrap(

        this Func<string, double> inner,

        char split,

        Func<double, double, double> aggregate)

    {

        return expression => expression

            .Split(split)

            .Select(inner)

            .Aggregate(aggregate);

    }

}

It definitely doesn’t take parenthesis into account, but it quite elegantly solves four arithmetic operations with operator precedence and more than two arguments and more than one operator per expression. Without using Linq I would probably go with a bunch of if/else statements being than refactored into an expression parser and an expression tree evaluator (which is a way to go for supporting parenthesis). Anyway for the first iteration I implemented all the features I wanted and ended up with very little code, which I don’t mind to throw away if it doesn’t fit anymore. And this is a true virtue of TDD.

The next Coding Dojo at the User Group Rhine/Ruhr will be on 27th April, hosted by MT AG in Ratingen. Follow announcements of the UG or sign up at Xing.

Advertisements

Written by Sergey Shishkin

11.04.2011 at 16:15

Posted in Uncategorized

2 Responses

Subscribe to comments with RSS.

  1. Elegante Lösung. Zeigt die Kraft, die in Lambdas steckt.

    Ob die Lösung allerdings gut verständlich ist oder evolvierbar… das steht für mich auf einem anderen Blatt 😉

    Ralf Westphal

    20.06.2011 at 08:07

    • Keine Frage. Schon bei Klammern, werde ich den Code wegschmeißen und einen richtigen ExpressionParser und einen TreeEvaluator bauen. Dafür ist die Lösung genau gut, weil die so kompakt ist.

      Zur Verständlichkeit: da hilft sicherlich bessere Benennung und allgemeines Verständnis des funktionalen Paradigma.

      Sergey Shishkin

      20.06.2011 at 20:19


Comments are closed.

%d bloggers like this: