Tuesday, 25 July 2017

Decorator pattern

Why?

I have a colleague who is officially a tester and scrummaster, and he has a growing interest in the code we (the developers) write. He asked a question this morning: "I've heard you talk about decorators, what are they?". I thought the best way to describe it is to write it down.

What?

The decorator pattern allows you to add functionality to a class without changing the underlying class. (See Open/Closed principle)

As an example, there's a class that reticulates splines:

Imagine you wanted to add logging to this class, to store the number of splines reticulated. You could add the logging directly into the class:

Alternatively you could add a decorator (literally "decorate" the class with new behaviour). The idea behind the decorator pattern is that the decorating class implements the same interface as the underlying class, and wraps an instance of the underlying class. This way it can pass through to the underlying instance, and add value along the way.
This gives you the ability of adding several layers of behaviour, and swapping in and out that behaviour as and when required:

Friday, 18 April 2014

Calling generic methods with runtime Type parameters

In the normal course of events, a call to a generic method needs to have its type resolved at compile time. For example, consider this class and method:
class TypeWriter
{
    public void WriteType<T>(TextWriter target)
    {
        target.WriteLine("T is {0}"typeof(T));
    }
}
This generic method needs to be called with its type parameter resolved at runtime, like this:
var typeWriter = new TypeWriter();
typeWriter.WriteType<Program>(Console.Out);
which gives this output:


But what do you do if you only discover the types at runtime so don't know the types at compile time? This commented code wouldn't compile because the variable assemblyType can't be resolved to a generic parameter:
foreach (var assemblyType in Assembly.GetExecutingAssembly().GetTypes())
{
    // typeWriter.WriteType<assemblyType>(Console.Out);
}

This is where System.Reflection comes in. The MethodInfo class has a method MakeGenericMethod that takes an array of System.Type, substitutes the method's generic parameters for the arguments and returns a new MethodInfo instance. This new MethodInfo instance can then be invoked like any other. Here's how this looks in code:
foreach (var assemblyType in Assembly.GetExecutingAssembly().GetTypes())
{
    // Get a handle on the method to call
    var method = typeof(TypeWriter).GetMethod("WriteType");

    // Pass the type parameter(s)
    var genericMethod = method.MakeGenericMethod(assemblyType);

    // Call the method on the TypeWriter instance, passing parameter(s)
    genericMethod.Invoke(typeWriter, new[] { Console.Out });
}
This gives the output:


Thursday, 3 April 2014

KeyedCollection

During a talk at DevWeek 2014 I discovered the KeyedCollection<TKey,TItem> class. The class is in the System.Collections.ObjectModel namespace, and is an alternative to the Dictionary<TKey,TValue> for items where the key is embedded in the item itself. The following code sample shows where it pays dividends to use a KeyedCollection over a Dictionary.

The following program creates a dictionary of Person objects; it uses the Id of the Person as the key, and the person itself as the value:


Bearing in mind that this is a contrived example, there is a problem with this code; having to specify the key manually has lead to a typo (didn't you spot it?):


If the key to use for your collection item can be derived from the value, the KeyedCollection allows you to do that.
The KeyedCollection class is abstract, so you need to inherit from it. Having done so, you can override the GetKeyForItem method; this is the method that the framework calls to obtain the key of the item:


Items can then be added to the collection as you would any collection, either using the Add method, or an object initialiser as I've done here:


When retrieving an item, the KeyedCollection behaves like a Dictionary rather than a List, because you access items by their key rather that their position in the collection:


See more about the KeyedCollection class on MSDN: http://msdn.microsoft.com/en-us/library/ms132438(v=vs.110).aspx

System.BitConverter Class

Every now and again a new framework class comes to my attention. At DevWeek I was attending a talk on Cryptography and an incidental part of the talk featured the BitConverter class. This is a class in the System namespace and has a bunch of static methods that convert to and from a byte array.

The ToString(byte[]) method was the one that I saw being used. It takes an array of bytes and converts each byte to its 2 character hexadecimal equivalent. This is an alternative to Base64 encoding and is arguably more human-friendly.




Other methods on the BitConverter class allow you to convert between a byte array and numerical types:

For more details, see the MSDN documentation at http://msdn.microsoft.com/en-us/library/system.bitconverter(v=vs.110).aspx

Thursday, 31 October 2013

Faking AppSettings in tests

If you have some code that uses configuration from an app.config or web.config file, and you need to retrospectively write tests for it, there are several approaches you can take to get fake setting into your tests.

Given this code
using System;
using System.Configuration;
using System.IO;

namespace Demo
{
    class Program
    {
        static void Main(string[] args)
        {
            using (var writer = new StringWriter())
            {
                new SeasonWriter().WriteSeason(writer);
                Console.WriteLine(writer);
                Console.ReadLine();
            }
        }
    }

    public class SeasonWriter
    {
        public void WriteSeason(TextWriter textWriter)
        {
            var month = ConfigurationManager.AppSettings["Month"];
            switch (month)
            {
                case "January":
                case "February":
                case "December":
                    textWriter.Write("Winter");
                    break;
                case "March":
                case "April":
                case "May":
                    textWriter.Write("Spring");
                    break;
                case "June":
                case "July":
                case "August":
                    textWriter.Write("Summer");
                    break;
                case "September":
                case "October":
                case "November":
                    textWriter.Write("Autumn");
                    break;
                default:
                    throw new ConfigurationErrorsException("No setting defined for 'Month'."
                        + Environment.NewLine
                        + "Please add a setting to the .exe.config file under the section AppSettings."
                        + Environment.NewLine
                        + "For more info on the .exe.config file, follow this link "
                        + "http://msdn.microsoft.com/en-us/library/vstudio/1fk1t1t0(v=vs.110).aspx");
            }
        }
    }
}
In order to get tests around the SeasonWriter class, the AppSettings entry "Month" needs to be faked or abstracted. Some options are:

Create an app.config file in the test project

This is the most obvious starting point. Create a test project to contain the SeasonWriterTests file, with an app.config containing a "Month" entry:
<appSettings>
  <add key="Month" value="January"/>
</appSettings>
using NUnit.Framework;
using System.IO;

namespace Demo.Test
{
    [TestFixture]
    public class SeasonWriterTests
    {
        [Test]
        public void WriteSeasonExpectWinter()
        {
            var writer = new StringWriter();
            var target = new SeasonWriter();
            target.WriteSeason(writer);
            Assert.That(writer.ToString(), Is.EqualTo("Winter"));
        }
    }
}
This will allow the test to run, but will limit you to testing a single path through the code. It's also flaky, because your test depends on a magic string in a separate file.

Pass the configuration setting in


This solution is a refactor of the WriteSeason method, so it takes the config setting in as a string. This sounds like a clean fix, with benefits
  • the responsibility for getting that value has been handed off to the user of the method
  • the code is easier to test

However, there are downsides
  • the refactor is an untested change
  • there could be many users of this method, and each one would be responsible for getting the month value
  • the exception type in the WriteSeason method is no longer correct

Set the config value


The easiest way to fake an AppSettings value is just to set it in your test class. ConfigurationManager.AppSettings is just a NameValueCollection, and items can be written as well as read:
using NUnit.Framework;
using System.IO;
using System.Configuration;

namespace Demo.Test
{
    [TestFixture]
    public class SeasonWriterTests
    {
        [TestCase("January""Winter")]
        [TestCase("February""Winter")]
        [TestCase("March""Spring")]
        [TestCase("April""Spring")]
        [TestCase("May""Spring")]
        [TestCase("June""Summer")]
        [TestCase("July""Summer")]
        [TestCase("August""Summer")]
        [TestCase("September""Autumn")]
        [TestCase("October""Autumn")]
        [TestCase("November""Autumn")]
        [TestCase("December""Winter")]
        public void WriteSeasonExpectCorrectSeasonForMonth(string month, string expectedSeason)
        {

          ConfigurationManager.AppSettings["Month"] = month;

            var writer = new StringWriter();
            var target = new SeasonWriter();
            target.WriteSeason(writer);
            Assert.That(writer.ToString(), Is.EqualTo(expectedSeason));
        }
    }
}

Friday, 25 October 2013

Disposable HtmlHelper Extensions

If you're regularly using a block of HTML elements consisting of opening tags and closing tags, you might want to employ the using pattern used by the framework's FormExtensions:


This is pretty straightforward; you need to create a class that implements IDisposable and render the opening tags in the constructor, and the closing tags in the Dispose method.

As an example I'll implement an HtmlHelper extension that renders a multi-column table with a header row containing the column titles specified, that will be rendered like this:


The first step is to create a static class for the extension method, and the extension method itself. This should be an extension method for the HtmlHelper object, and needs to return an instance of a class that implements IDisposable:


The HtmlHelper exposes a ViewContext, which has a Writer property; this is a TextWriter, and it's this object that stores the HTML that will be sent to the HttpResponse. The writer is the object that we need to pass our HTML string to. For this example, I also need the headers to render, so I've added a params parameter to the extension method:


The implementation of the disposable helper constructor builds and writes the table header, and the dispose method writes the closing tag:


The usage of the helper in the view can be changed to this:


Or this:


And gets rendered like this:


The code for the example helper class is available as a GitGist