Decorator or Russian Dolls (part 2)

It has taken a few weeks, but i have finished an implementation of “extras” in the making a cuppa instructions app. Part 1, for those that missed it. All the code can be found on github, https://github.com/chrishey/CupOfCoffee-DecoratorPattern

So ideally i wanted to keep a similar style to getting the extras, passed in via the command line. I also wanted to be able to specify via the command line what beverage i was making. So lets tackle that last one first.

First i brought in a command line args parser (see the git repository to see how it works) to read the arguments and give me an dictionary of arguments and their values to work with. In our initial Main method now we can read the “drink” argument and from there initialise the right beverage type class.


if (args.Length == 0)
{
Console.WriteLine("Sorry, we couldn't find your beverage");
}
else
{
var commandLineArgs = new CommandLineArgsParser(args);

switch (commandLineArgs["drink"].ToLower())
{
case "tea":
var tea = new Tea();
tea.CuppaFather();
break;
case "coffee":
var coffee = new Coffee();
coffee.CuppaFather();
break;
default:
Console.WriteLine("Sorry, we couldn't find your beverage. Would you like a cuppa Tea, Father?");
break;
}
}

We can now run the program to give us instructions to make us a cup of tea

makebrewdrink

Moving swiftly on past that small hurdle, I started thinking (and hacking) about how to get extras in. I wanted extras, whatever they were to be an IStep, so i could chain them. I also need a quantity potentially on an extra i.e. spoons of sugar. I tried a few ways to do this and after several failed attempts to make it work 100% cleanly i ended up with the following.

An extra always has a quantity, so let’s create a class to hold that.


public class Extra
{
protected readonly int Quantity;

public Extra(int quantity)
{
Quantity = quantity;
}
}

We can now use this as base for all extras and inject the quantity in via the constructor. I also wanted the extras to implement IStep so i can keep calling .Do() if another IStep is injected into it.


public class AddSugar : Extra, IStep
{
private readonly IStep _step;

public AddSugar(IStep step, int quantity):base(quantity)
{
_step = step;
}

public void Do()
{
Console.WriteLine(string.Format("Add {0} spoons of sugar", Quantity));

if (_step == null)
return;

_step.Do();
}
}

As you can see here, we take an IStep instance and a quantity in the constructor of an extra. We pass the quantity to the base, print out our instruction and then see if we have a subsequent step to call. I now needed to put this together with the command line arguments along the lines of Make.exe -drink tea -sugar 2. Due to the quantity constructor parameter it wasn’t just a case of chaining the extras into the Tea/Coffee class, also there might be multiple extras and i need to know their names and what instances to create.

My solution was to read any extras off the command line arguments.


var commandLineArgs = new CommandLineArgsParser(args);

var extras = GetExtras(commandLineArgs);

Where GetExtras is as follows:


private static Extra[] GetExtras(CommandLineArgsParser commandLineArgs)
{
var extras = new List();

if (commandLineArgs["sugar"] != null)
{
var sugar = int.Parse(commandLineArgs["sugar"]);
extras.Add(new AddSugar(null, sugar));
}

return extras.ToArray();
}

Not ideal and it does “itch” with me a bit, but it works, which some of my other attempts didn’t. In this example we aren’t passing in another step, just the amount of sugar off the arguments. I also have to know the name of the extra to deal with it, i couldn’t see how to do this dynamically, this might be part 3! 🙂

Now the Tea and Coffee classes need to accept these extras to add the instructions.


public class Tea : BrewUp
{
private readonly Extra[] _extras;

public Tea(Extra[] extras) : base (new FillKettle(new BoilKettle(new AddTeaBag(new AddMilk(null)))))
{
_extras = extras;
}

public new void CuppaFather()
{
base.CuppaFather();

if (_extras.Any())
{
foreach (var extra in _extras)
{
var step = extra as IStep;
if (step != null) step.Do();
}
}
}
}

We move through the ISteps via the BrewUp method of CuppaFather and then if we have extras we loop through them and call any subsequent ISteps chained onto them.

makeabrewwithextras

We can now get extras like sugar printed out in our instructions.

Any feedback or possible tweaks to the solution are very welcome. The code is there on Github, fork it and send a pull request or get in contact.

Thanks for reading….i am off to make a brew!

Posted in Uncategorized.

Decorator Pattern or Russian Dolls

We were discussing at work a scenario where you would want to be able to execute behaviours from a controlling block of code and pass in many types of common behaviours. My mind went straight to abstract and base classes to solve it. However someone said it can be done using composition over inheritence. It is not something I had considered before and was interested to find out more and see if i could implement something similar in C#.

So given that i am partial to a hot beverage i decided to use the steps to prepare different types of these as they have shared steps or behaviours. i.e. boiling hot water, adding sugar, milk and pouring hot water into the cup. I started with the idea of an interface to represent the step.


public interface IStep
{
void Do();
}

I then create a class with one method on it to call the Do method on a step. The CuppaFather method being inspired by Mrs Doyle from Father Ted. The class constructor take an instance of IStep and the CuppaFather method calls the Do method on it.


public class BrewUp
{
private readonly IStep _step;

public BrewUp(IStep step)
{
_step = step;
}

public void CuppaFather()
{
_step.Do();
}
}

I can then implement IStep for as many steps as i can think of for making say a cup of coffee. So fill the kettle, boil it, add coffee to the mug, pour the hot water in and add milk. (Or milk first, i am not getting into THAT debate though) So here is the code to fill the kettle for instance. Note how it also has a constructor taking an IStep instance. When its Do method is called we check to see if we got an IStep instance and if so we call it’s Do method, thereby chaining the steps/behaviours together.


public class FillKettle : IStep
{
private readonly IStep _step;

public FillKettle(IStep step)
{
_step = step;
}

public void Do()
{
Console.WriteLine("Filling the Kettle");

if (_step == null)
return;

_step.Do();
}
}

This is then pull together into a console app by passing in new instances of each step to the previous one.


class Program
{
static void Main(string[] args)
{
var brewUp = new BrewUp(new FillKettle(new BoilKettle(new AddCoffeeToCup(new AddMilk(null)))));
brewUp.CuppaFather();
Console.ReadKey();
}
}

This gives us an output of the steps to make a basic cup of coffee…not very exiciting so far.

beveragemaker

What we really want is to be able to input the hot beverage we want steps for and get those steps back reusing the common steps, maybe even add in some “extras” like chocolate sprinkles or sugar (and the number of spoons).

That is for another time…

Part 2 now published Decorator or Russian Dolls Part 2

Posted in Uncategorized.

Razor view anonymous models

I stumbled across this issue this morning…

'object' does not contain a definition for 'Error'

Description: An unhandled exception occurred.

Exception Details: Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: 'object' does not contain a definition for 'Error'

@if (Model != null) {@Model.Error}

Basically the anonymous type on the model is internal and can only be accessed by the assembly in which it is declared. Views get compiled separately and therefore can’t access the property.

How to fix it…

I found a nice little extension class referenced on stackoverflow


public static ExpandoObject ToExpando(this object anonymousObject)
{
IDictionary anonymousDictionary = new RouteValueDictionary(anonymousObject);
IDictionary expando = new ExpandoObject();
foreach (var item in anonymousDictionary)
expando.Add(item);
return (ExpandoObject)expando;
}

You then create your (very basic) anonymous model as follows:


const string error = "error message";

return View("viewname", new {Error = error}.ToExpando());

The razor view code is then as before:

@if (Model != null) {@Model.Error}

Posted in Uncategorized.

Prototyping with scriptcs and building in Nancy

I had a project brief to work with an API the other day at work and it wasn’t one I was familiar with. Looking at the documentation for it I knew I wanted to hit some of the endpoints, get the responses and analyse the data before I dived in and started writing anything. I am a NancyFx convert, I like how easy it is to build any kind of web/HTTP based application. The speed and lightweight feel of it just sits well with me. However in this instance I want to dive into making API requests even faster than opening Visual Studio, picking a NancyFX template and creating some routes to return data from the API via my browser.

So how to do it?

I happened to go into the scriptcs session at the NDC London conference done by one of the founding fathers Glenn Block. Could I use this?

Well the answer is yes I could and it was great fun into the bargain! I won’t go through how to install it, how cool Chocolatey is (it really is) as the guide on the site will do a better job. http://scriptcs.net

Yes, you have to know your way round what is in what namespace and get the right using statements (I have Notepad++ as my text editor, there is a plugin for scriptcs, which helps but doesn’t seem to bring in usings, I know there is a plugin for SublimeText maybe it is better? If so I would love to hear from you!). Personally I see this as a challenge to my own knowledge of the framework and part of my continued learning. Anyway it was nice to be able to jump into prototyping the API calls and seeing results quickly in the command line.

I put the following code into my text editor (removing the api key and location of the saved file on my machine) and saved it as ProjectsBoards.csx:


#r "Newtonsoft.Json.dll"

using System.Net;
using System.Collections.Specialized;
using System.IO;
using Newtonsoft.Json;

using (var client = new WebClient())
{
var data = new NameValueCollection();
client.Headers.Add("apikey", "<APIKeyValue>");

var response = client.UploadValues("http://kanbanize.com/index.php/api/kanbanize/get_projects_and_boards/format/json", "POST", data);
var responseString = Encoding.Default.GetString(response);
File.WriteAllText(@"<filelocation>\projects-and-boards.json", responseString);
}

To run this script (after installing scriptcs obviously), you open a command prompt navigate to the directory you save your file and type:

scriptcs ProjectsBoards.csx

Alternatively you could give the scriptcs command the full path to your script file.

Now I have a JSON file I can look at, analyse and determine how I can use it in my application. I can parametrise the script and pass in the API endpoint and file name of where I want the data to be saved.


#r "Newtonsoft.Json.dll"

using System.Net;
using System.Collections.Specialized;
using System.IO;
using Newtonsoft.Json;

using (var client = new WebClient())
{
var data = new NameValueCollection();
client.Headers.Add("apikey", "enter api key");

var response = client.UploadValues(Env.ScriptArgs[0], "POST", data);
var responseString = Encoding.Default.GetString(response);
File.WriteAllText(@Env.ScriptArgs[1], responseString);
}

I can call this script as follows:

scriptcs Parameterised.csx -- http://kanbanize.com/index.php/api/kanbanize/get_projects_and_boards/format/json path\to\file

Now I can hit any endpoint and write a file out with the results (reusable!). I passed each result into http://json2csharp.com/ to generate POCOs for use in the Nancy application.

I then switched into Visual Studio and created my project using the Nancy application template with ASP.NET hosting and Razor with the knowledge of what data I was working with and some POCOs to start me off. Also performing this rapid prototyping with scriptcs had got me to consider that the API call needs parametrising in my application and encapsulating correctly. I can also quickly try out optional parameters on the API calls without having to change my application and roll it back if I am not happy with the results.

By using this approach I haven’t created an application I then scrapped or refactored once I knew more about the 3rd party API I was using. Plus it was good fun to use something new and see if it improved the overall development experience.

Posted in Uncategorized.