Skip to content

A Fluent Builder in C#

2010 April 14
by stefanoricciardi

When it comes to the number of arguments to pass to a function, Uncle Bob is pretty clear. Quoting from Clean Code:

The ideal number of arguments for a function is zero (niladic). Next comes one (monadic), followed closely by two (dyadic). Three arguments (triadic) should be avoided when possible. More than three (polyadic) requires very special justification – and then shouldn’t be used anyway.

Still, some objects might have more than 3 attributes or properties and you usually need some way to initialize them via the constructor. Some attribute might not be mandatory, therefore on some occasions you can get by with a few overloads adding more parameters as needed.

Consider the following (contrieved) example from the world of soccer. I have picked a few attributes that encapsulate the concept of a Team.

namespace Soccer
{
    public enum Color
    {
        White,
        Red,
        Green,
        Blue
    }

    public class Team
    {
        string Name { get; set; }
        string NickName { get; set; }
        Color ShirtColor { get; set; }
        string HomeTown { get; set; }
        string Ground { get; set; }

        public Team(
            string name,
            string nickName,
            Color shirtColor,
            string homeTown,
            string ground)
        {
            Name = name;
            NickName = nickName;
            ShirtColor = shirtColor;
            HomeTown = homeTown;
            Ground = ground;
        }
    }
}

Let’s try initializing one team:

Team team1 = new Team(
    "Manchester United",
    "The Red Devils",
    Color.Red,
    "Manchester",
    "Old Trafford");

In this case we are passing 5 arguments into the constructor. Consider that most of the parameters is a string, therefore it’s quite easy to get confused and invert the order of some parameter (the first two or the last two). The compiler would not be able to help in this case.

What may help here is a builder object with a fluent interface which can help specifying all the attributes of the team. Something like the following:

TeamBuilder tb = new TeamBuilder();
Team team2 =
    tb.CreateTeam("Real Madrid")
        .WithNickName("Los Merengues")
        .WithShirtColor(Color.White)
        .FromTown("Madrid")
        .PlayingAt("Santiago Bernabeu")
        .Build();

Let’s see the code for the TeamBuilder class:

public class TeamBuilder
{
    private string name;
    private string nickName;
    private Color shirtColor;
    private string homeTown;
    private string ground;

    public TeamBuilder CreateTeam(string name)
    {
        this.name = name;
        return this;
    }

    public TeamBuilder WithNickName(string nickName)
    {
        this.nickName = nickName;
        return this;
    }

    public TeamBuilder WithShirtColor(Color shirtColor)
    {
        this.shirtColor = shirtColor;
        return this;
    }

    public TeamBuilder FromTown(string homeTown)
    {
        this.homeTown = homeTown;
        return this;
    }

    public TeamBuilder PlayingAt(string ground)
    {
        this.ground = ground;
        return this;
    }

    public Team Build()
    {
        return new Team(name, nickName, shirtColor, homeTown, ground);
    }
}

The only catch in the solution above is that the caller needs to call Build() at the end of the call chain.

We can improve the solution using an implicit user-defined type conversion operator:

public class TeamBuilder
{
    private string name;
    private string nickName;
    private Color shirtColor;
    private string homeTown;
    private string ground;

    public TeamBuilder CreateTeam(string name)
    {
        this.name = name;
        return this;
    }

    public TeamBuilder WithNickName(string nickName)
    {
        this.nickName = nickName;
        return this;
    }

    public TeamBuilder WithShirtColor(Color shirtColor)
    {
        this.shirtColor = shirtColor;
        return this;
    }

    public TeamBuilder FromTown(string homeTown)
    {
        this.homeTown = homeTown;
        return this;
    }

    public TeamBuilder PlayingAt(string ground)
    {
        this.ground = ground;
        return this;
    }

    // CONVERSION OPERATOR
    public static implicit operator Team(TeamBuilder tb)
    {
        return new Team(
            tb.name,
            tb.nickName,
            tb.shirtColor,
            tb.homeTown,
            tb.ground);
    }

This allows you to create new teams in a more natural way as follows:

TeamBuilder tb = new TeamBuilder();

Team team3 = tb.CreateTeam("Chelsea")
    .WithNickName("The blues")
    .WithShirtColor(Color.Blue)
    .FromTown("London")
    .PlayingAt("Stamford Bridge");

The above solution, albeit quite simple, is a good starting point. To make it ready for real-world code, you should making it more robust with some error checking (what happens if I omit some call from the chain? If I pass an invalid argument? Etc…).

More, you might want to hide the actual implementation from the clients and extract an interface or abstract class from the concrete TeamBuilder. This is left to the reader as an excercise :)

kick it on DotNetKicks.com


Shout it

Book Review: Pragmatic Thinking And Learning

2010 April 5
tags: ,
by stefanoricciardi

Since you are reading this blog I assume that you are a software developer, or more in general a “knowledge worker” as Peter Drucker refers to the person “who puts to work what he has between his hears rather than the brawn of his muscles or the skill of his hands” in his excellent book Effective Executive.

And if you try to keep up to date by reading books, blogs, listening to podcasts, etc… I sure don’t have to tell you how difficult it is staying on top of new technologies, frameworks, languages which come out quicker and quicker. It’s sure impossible to keep up with everything.

Trying to come up with some new ideas on how tackle this issue, I have picked up the book Pragmatic Thinking and Learning: Refactor Your Wetware by Andy Hunt with high expectations, having loved The Pragmatic Programmer (see my review of that book here) where Andy Hunt was one of the two authors. And I must say that I have not been disappointed: Pragmatic Thinking and Learning is another great book.

Let’s have a quick look to the contents.

From Novice To Expert

The book first focuses on describing a few phases one goes through in his learning journey. The Dreyfus brothers have tried to formalize the steps to reach the expert status on a given skill (like practicing a sport or programming using a particular language) in the following way:

  • Novice: you start from here and for basically everything you have to do you need a “recipe”.
  • Advance Beginner: you now start trying things on your own, and need reference documentation (think of a list of API)
  • Competent: you have more initiative, can troubleshoot existing problems and solve new ones.
  • Proficient: at this stage you are more self-conscious of your own skill and want to understand the larger picture. This feedback is vital for your continuous improvement.
  • Expert: at this stage you keep looking for better ways of doing things. You tend to work from intuition as opposed to a fixed set of rules and reason: you just ten to “feel” what’s right in any given situation.

How Your Brain Works and How To Make The Best Use of It

The model put forward of your brain here is that of a “dual core” CPU. But the two halves don’t work the same way:

  • L-Mode: this is your linear mode(traditionally associated with the left hemisphere): analytical, rational, verbal. This is perhaps the part of our brain that we are most familiar with in our day-to-day activities as software developers.
  • R-Mode: intuitive, analogic, non-rational. These are the traits most commonly associated with artists.

This major section of the book explains why, as a knowledge worker, you need both modes to fully exploit your abilities, and gives tips on how to “shut up” the L-Mode for a while so that you can engage more the R-mode.

It then goes on to help you “debug” your thinking process, introducing several cognitive biases (things such as “self serving bias”, “hawthorne effect”, “false memory”) and explains that many of your hard-coded thought patterns might just be due to the generation you belong to (are you in the Baby Boom Generation, in the Generation-X or in the Millennial Generation?).

Learn to Learn and Gain Experience

The book then concentrates on the best practices to learn:

  1. You need to set SMART objectives for what you want to reach. Having a plan will keep you focused.
  2. You need to consider your skills as a knowledge portfolio. You need to diversify the areas you decide to invest in and dedicate some quality time to it regularly (which requires planning some time in advance: trying to find some free hours here and there simply doesn’t work…).
  3. You need to discover how you learn best. Do you prefer books and videos (visual) or podcasts (audio)? Consider joining a study group,
  4. Use advanced learning techniques such as SQ3R, or mind mapping. Teach to others.
  5. We learn best by doing: explore, play (= have fun) with the concepts, gets your hand dirty. Experiment and don’t be afraid to make mistakes, possibly in a non-stressful situation (you don’t want to have the pressure of a “real” work project).

Keep the Focus

The last part of the book has is somehow lighter and it’s dedicated to ways to increase your focus and attention. The author touches upon different topics from meditation to productivity tricks: if you have been exposed to productivity blogs such as Lifehacker you are like to be familiar with most of these already

Conclusions

This has really been a fun book to read and I whole-heartedly recommend it. I have gone back to it quite a few times already after reading it from cover to cover.

Each small chapter contains a “Next Actions” section with exercises and goals for you to try out and throughout the book there are tons of references if you are interested in a particular topic and want to dig more.

It used to be that all you needed to perform your job was “The C Programming Language”. That’s not the case any more.

If I had eight hours to cut down a tree, I’d spend six hours sharpening my ax. — Abraham Lincoln.

Shout it

Comparing Floating Point Numbers

2010 March 2
tags: , ,
by stefanoricciardi

Floating Points and Rounding Errors.

Working with floating points number can sometimes provide some (un)pleasant surprise, since many real numbers do not have a finite representation and this can lead to rounding errors.

If you need to refresh your knowledge (and have some time to spare), you can find a great treatment in the article What Every Computer Scientist Should Know About Floating-Point Arithmetic:

Squeezing infinitely many real numbers into a finite number of bits requires an approximate representation. Although there are infinitely many integers, in most programs the result of integer computations can be stored in 32 bits. In contrast, given any fixed number of bits, most calculations with real numbers will produce quantities that cannot be exactly represented using that many bits. Therefore the result of a floating-point calculation must often be rounded in order to fit back into its finite representation. This rounding error is the characteristic feature of floating-point computation.

A small example should make the problem clearly visible:

class Program
{
    static void Main(string[] args)
    {
        double a = 22.4;
        double b = a / 131;

        double c = 0;
        for (int i = 0; i < 131; i++)
        {
            c += b;
        }

        Console.WriteLine("Are they equal?: {0}", a == c);
        Console.WriteLine("Difference (a - c) is {0} ", a - c);
    }
}

Here we are taking a double (a), diving it by 131 and then creating a new number (c) by adding the result of that division 131 times. By pure math, a and c should be equal. If you try this small program yourself, this is the output that you would get:

Are they equal?: False
Difference (a - c) is -4,9737991503207E-14

As you can see, the result is not what you might expect, and it's affected by a rounding error that is building up every time b is added to the partial result c.

Note that this is dependent on the number that I have chosen. If you substitute 131 with 5, you will not experience this problem.

Your Own Comparer

Sometimes this behavior might annoy you, especially when you don't need such a high precision and a “rough” equality is all you need. A typical situation is unit testing an algorithm against some expected result: your assertions may fail because of a rounding error, even though the logic of your algorithm is formally correct.

In such a case, you might want to implement your own comparer. A desirable property for such a comparer is a threshold value: if the difference between two floating points is below that threshold they are considered equal.

All you need is to implement the .NET interface IEqualityComparer interface.

class DoubleComparer : IEqualityComparer
{
    private readonly double threshold;

    public DoubleComparer(double threshold)
    {
        this.threshold = threshold;
    }

    public bool Equals(double x, double y)
    {
        return Math.Abs(x - y) < this.threshold;
    }

    public int GetHashCode(double obj)
    {
       return obj.GetHashCode();
    }
}

I have created my own comparer to use in my unit tests. I only have to implement 2 methods: Equals() and GetHashCode().

I don't care much for the actual algorithm of the hashcode implementation, so I am reusing double own algorithm.

Instead, I have applied my own logic to the Equals method: to me, two doubles are equal if the absolute value of their difference is within a given threshold (which I can pass to the comparer in the constructor).

The Comparer In Use

Suppose I have an algorithm to calculate the histogram of a given collection of doubles, and a unit test to validate the calculation against a collection of expected results.

In the example below, samples are the input values which I want to create the histogram for, and expectedBreaks is a sequence containing the left and right limits of the bins of the histogram (in the example I am requiring 5 bins, so the number of breaks is 5 + 1 = 6).

var p = new HistogramProvider();
double[] samples = { 20, 12, 4, 22, 19, 24, 9, 5, -12.2, 13, 0 };
double[] expectedBreaks = { -12.2, -4.96, 2.28, 9.52, 16.76, 24 };

var histogram = p.CreateHistogram(samples, 5);

Assert.IsTrue(expectedBreaks.SequenceEqual(
                       histogram.Breaks,
                       new DoubleComparer(0.01)));

I have figured out the threshold to pass (0.01) based on the relative size of the doubles under analysis. Of course, you should use your own judgement to come up with a sensible threshold according of the range of your input data.

kick it on DotNetKicks.com

Shout it

8 visitors online now
8 guests, 0 members
Max visitors today: 8 at 12:47 am CEST
This month: 8 at 08-01-2010 12:47 am CEST
This year: 40 at 05-03-2010 04:48 am CEST
All time: 40 at 05-03-2010 04:48 am CEST