Tuesday, 22 May 2012

Visiting the visitor pattern

A colleague of mine showed me the following result.


----------------------------------------------------------------
Current Drawing
----------------------------------------------------------------
Rectangle (10,10) width=30 height=40
Square (15,30) size=35
Ellipse (100,150) diameterH = 300 diameterV = 200
Circle (1,1) size=300
Textbox (5,5) width=200 height=100 Text="sample text"


He asked me whether I can write a simple console application to achieve the above result. Simple task you might say.

Well.. it is pretty obvious that we need to start off with an abstract "Shape" class. But what about the logic to "draw" the shape on the canvas. What we need is an interface like "ICanDraw", which contains the "draw" method. Now, the Shapes can be drawn, therefore the Shape should implement the "ICanDraw" interface. But hang on, each Shape should present itself to the canvas. The canvas should then decide how to "draw" the shape on the canvas.

The most interesting piece here is the text box.  A text box is not strictly a shape, but a "Rectangle" with a additional text property. We can say that a text box is composed of a Rectangle. Internally the text box will use the Rectangle to represent itself.

See the following UML.



My "ICanDraw" interface looks like below.


    /// <summary>
    /// This interface indicates that the shape can be drawn.
    /// </summary>
    public interface ICanDraw
    {
        void Draw(ICanvas canvas);
    }


The abstract "Shape" class looks like below.


    /// <summary>
    /// This is the base class for a shape.
    /// </summary>
    public abstract class Shape : ICanDraw
    {
        public int X { getprivate set; }
 
        public int Y { getprivate set; }
 
        protected Shape(int x, int y)
        {
            X = x;
            Y = y;
        }
 
        public abstract void Draw(ICanvas canvas);
    }


Keep a close eye on the abstract "Draw" method. Also notice that the "X" and "Y" are "readonly" properties. This plays nicely to the immutability of objects

The "Circle" class looks like below:


    /// <summary>
    /// This is the concrete implementation of a circle.
    /// </summary>
    public class Circle : Shape
    {
        public int Size { getprivate set; }
 
        public Circle(int x, int y, int size)
            : base(x, y)
        {
            Size = size;
        }
 
        public override void Draw(ICanvas canvas)
        {
            canvas.Draw(this);
        }
    }


The code for the text box looks like below.


    /// <summary>
    /// This is the concrete implementation of a text box.
    /// </summary>
    public class Textbox : ICanDraw 
    {
        public Rectangle Rectangle { getprivate set; }
 
        public string Content { getprivate set; }
 
        public Textbox(int x, int y, int width, int height, string content)
        {
            Rectangle = new Rectangle(x, y, width, height);
            Content = content;
        }
 
        public void Draw(ICanvas canvas)
        {
            canvas.Draw(this);
        }
    }


Ok, we have all the concrete classes and a special text box.

Next piece of the puzzle is the "ICanvas". Since we are just writing the content to the console, this will be a special console canvas. The canvas is aware of the shapes and will decide how to draw them. The responsibility to draw a shape is now with the canvas.

The following is the special implementation of "ICanvas" for the console.


/// <summary>
    /// This is the "canvas" representing the console.
    /// </summary>
    public class ConsoleCanvas : ICanvas 
    {
        public void Draw(Circle item)
        {
            Console.WriteLine("Circle({0},{1}) Size={2}", item.X, item.Y, item.Size);
        }
 
        public void Draw(Rectangle item)
        {
            Console.WriteLine("Rectangle({0},{1}) Width={2}, Height={3}", item.X, item.Y, item.Width, item.Height);
        }
 
        public void Draw(Square item)
        {
            Console.WriteLine("Square({0},{1}) Size={2}", item.X, item.Y, item.Size);
        }
 
        public void Draw(Ellipse item)
        {
            Console.WriteLine("Ellipse({0},{1}) DiameterH={2}, Diameter={3}", item.X, item.Y, item.DiameterH, item.DiameterV);
        }
 
        public void Draw(Textbox item)
        {
            Console.WriteLine("TextBox({0},{1}) Width={2}, Height={3}, Text={4}", item.Rectangle.X, item.Rectangle.Y, item.Rectangle.Width, item.Rectangle.Height, item.Content);
        }
    }


As you can see the canvas is aware of the shapes and it decides how to draw them. The canvas will determine this by the runtime type of the object.

Can you see a pattern here? This is in fact the "Visitor" pattern. The purpose of the visitor pattern is to choose a functionality depending on the run-time type of an object. The pattern is also used to introduce additional functionality to an object.

So how do we "draw" these shapes. See below.


        private static void Load()
        {
            var items = new List<ICanDraw>()
                            {
                                new Rectangle(10, 10, 30, 40),
                                new Square(15, 30, 35),
                                new Ellipse(100, 150, 300, 200),
                                new Circle(1, 1, 300),
                                new Textbox(5, 5, 200, 100, "Sample Text")
                            };
 
            items.ForEach(item => item.Draw(new ConsoleCanvas()));
        }

The special "ConsoleCanvas" visits each shape and "draws" it on the console.

In terms of SOLID principals, the "Shape" class is open for extensions and closed for modifications . Yes, the Open/Close principal.

But can the same functionality be achieved through another pattern?

Saturday, 5 May 2012

State and Strategy patterns

The State and Strategy patterns are very similar to each other but their use is somewhat different.

The state pattern is a way of encapsulating the behaviour of each state an object goes through. The state pattern fits nicely to model the operation of an ATM machine.

The key difference is that the state pattern is used to identify "states" which an object goes through. Where as the strategy pattern encapsulates a behaviour of the object. The state classes can be aware of the other states. This raise the question of coupling. For a system that is dynamically changing, then having states "knowing" other states might be acceptable.

The strategy on the other hand is an isolated functional unit and there is no interaction between the strategies. The context can choose which strategy to use where as the state is changed by changes to the internal state of the object. The most obvious way to use the strategy pattern is with the factory method.

Thursday, 3 May 2012

My battle with TFS 2010 Custom Activity (2)

So how does MSBuild activity works in the TFS 2010 build template. For that we need to have a closer look at the MSBuild activity.

See the following. I have highlighted the most important piece of information. The "OutDir" is the directory where the binaries are copied once a project has build successfully.



If this property is set to empty, the build output of a project will remain in the respective "bin" folder of each project (bin\Build configuration).

Therefore the first step is to set "OutDir" property to empty string.

The next step is to understand how the build process works.

We now need to look at the "Build Definition" process properties. (next post)

My battle with TFS 2010 Custom Activity (1)

I am sure by now you have seen the TFS 2010 build template. Pretty cool!

Normally if you build a solution is Visual Studio, the binaries can be found under the "bin" folder of each project. But if you notice the binaries coming out of a TFS 2010 build agent is dropped into a central location.

Some argue that this is a good solution. If you consider the references between project, having a folder for each project is very costly. The binaries can easily be duplicated over projects.

I recently had to make changes to the build process so that each project is built and dropped to a project specific folder. You might say that, surely TFS 2010 should support this level of customisation. But unfortunately this is far from being true.

I spend a whole day trying to figure out how to do this. Following are some solutions that I came across.


  1. Update to the Build Template Only
  2. Update to build template and each project in the solution


But my constrains were, no changes to the projects in the solution. Therefore solution (2) is out of the equation.

My expectation is below:

Drop folder/
               Project1
                    One.dll
                    Two.dll
              Project 2
                    Three.dll

The solution (1) is very promising but error prone. What if there are multiple solutions in the same workspace each using different projects? Then this method fails too.

So I am left is only a single solution, write my own custom activity.

My strategy is simple, build each project into their respective "bin" folders and copy the contents of the "bin" folder them across to the drop folder (under each project folder).

That is where the fun begin! (next post)