Wednesday, April 30, 2008

Generic reordering

Do you have items in your application that need to be ordered in some arbitrary, user defined order? Countries could very well be ordered alphabetically, but let's assume that one of our requirements is for arbitrarily ordered countries. Here's a user interface for this. The little green up and down arrows can be clicked to reorder the countries:

IOrderable

Here's the country table, note that it's got a position field that tells us the position of the country.

CountryTable

So, when I click an up arrow I just need to find the country above's position number and swap the current position number with it. This is all standard stuff. But what I want to show you today is how we can make a generic ordering component that can do all this stuff for us for any entity that implements an IOrderable interface:

public interface IOrderable
{
   int Position { get; set; }
}

Here's a snippet of my CountryController, note that I've got an instance of IOrderableService<Country> and two actions, 'MoveUp' and 'MoveDown'. All these two actions have to do is call MoveItemAtPosition(x).UpOne() or DownOne() in order to reorder the country.

public class CountryController : ControllerBase
{
 IOrderableService<Country> countryOrderableService;

 public CountryController(IOrderableService<Country> countryOrderableService)
 {
  this.countryOrderableService = countryOrderableService;
 }

 public ActionResult MoveUp(int id)
 {
  countryOrderableService.MoveItemAtPosition(id).UpOne();
  return RenderIndexView();
 }

 public ActionResult MoveDown(int id)
 {
  countryOrderableService.MoveItemAtPosition(id).DownOne();
  return RenderIndexView();
 }
}

This is one of the cool side effects of having a generic repository. See my previous post on Using the IRepository pattern with LINQ to SQL. Because of the generic repository we can write a generic ordering service for any entity.

Now consider these categories:

Categories

These are orderable but also nested. We only want to order an item within it's nested level. Here's a snippet of the category controller:

public class CategoryController : ControllerBase
{
   IOrderableService<Category> orderableService;

   public CategoryController(
       IOrderableService<Category> orderableService)
   {
       this.orderableService = orderableService;
   }

   public ActionResult MoveUp(int id)
   {
       Category category = categoryRepository.GetById(id);
       orderableService
           .MoveItemAtPosition(category.Position)
           .ConstrainedBy(c => c.ParentId == category.ParentId).UpOne();
       return RenderIndexView();
   }

   public ActionResult MoveDown(int id)
   {
       Category category = categoryRepository.GetById(id);
       orderableService
           .MoveItemAtPosition(category.Position)
           .ConstrainedBy(c => c.ParentId == category.ParentId).DownOne();
       return RenderIndexView();
   }
}

As you can see, this time we've got the same IOrderableService<T>, but now we're using ConstrainedBy and telling the service that we only want to reorder within the set of categories that have the same parent id. Since the constraint is a lambda expression we can have considerable scope for defining the constraint. In another part of the application products are constrained by their categoryId when reordering.

All the code for these examples is in my suteki shop application that you can check out from google code here:

http://code.google.com/p/sutekishop/

Have a look at the OrderableService and Move classes. You can see Suteki Shop in action here:

http://sutekishop.co.uk/home

Happy ordering!

Thursday, April 24, 2008

Last night's Sussex Geek Dinner

I had a lot of fun presenting my Inversion of Control talk yesterday and it was really nice to meet a load of old friends and a few new faces. Simon Harriyott did his usual great job of organizing the whole thing. It was also very nice of Cubeworks to lend us their projector. Thanks to Graham for bringing it along.

Here are a few links and resources:

You can find the source code for Suteki Shop the eCommerce application that I'm currently writing and that I used to demonstrate some of the principles at http://code.google.com/p/sutekishop/

You can also have a play with it at it's home here: http://sutekishop.co.uk/home

sutekishop

The home of the Windsor IoC container is here: http://www.castleproject.org/container/index.html

Oren Eini's (aka Ayende Rahein) IoC MSDN article is here: http://msdn2.microsoft.com/en-us/library/aa973811.aspx

His blog is here: http://www.ayende.com/Blog/

Monday, April 14, 2008

Problems with the MVC Framework RenderComponent helper method

I've just been having a frustrating time attempting to use the new HtmlHelper extension method in the MVC Framework CTP2, RenderComponent. There are so many problems with it that it's really not at all ready for any serious use. Here's a thread on the MVC forum dedicated to some of it's shortcomings:

http://forums.asp.net/t/1240638.aspx

When the MVC Framework was announced, several design goals were given including:

  1. It should allow for unit testing
  2. It should enable the use of IoC containers
  3. It should allow for multiple view engines

All three of these have been broken by RenderComponent. The base component type, ComponentController has one real method, RenderView. Here's what it looks like in Reflector:

public void RenderView(string viewName, object viewData)
{
   if (!viewName.EndsWith(".aspx", StringComparison.OrdinalIgnoreCase))
   {
       viewName = viewName + ".aspx";
   }
   string str = base.GetType().Name.Replace("Controller", "");
   ViewPage handler = (ViewPage) Activator.CreateInstance(BuildManager.GetCompiledType(("~/Components/" + str) + "/Views/" + viewName));
   handler.Url = new UrlHelper(this.Context);
   handler.Html = new HtmlHelper(this.Context);
   handler.SetViewData(viewData);
   StringBuilder sb = new StringBuilder();
   StringWriter writer = new StringWriter(sb, CultureInfo.CurrentCulture);
   HttpContext.Current.Server.Execute(handler, writer, true);
   string str4 = sb.ToString();
   this.RenderedHtml = str4;
}

The first thing to notice is that the RenderView method isn't virtual which means you can't mock it. I got around it with some horrible hackery. I defined an intermediate base class that my controller components use and I've hidden the RenderView method with a new virtual method.

public class ComponentControllerBase : ComponentController
{
   public ComponentControllerBase()
       : base()
   {
   }

   public ComponentControllerBase(ViewContext viewContext)
       : base(viewContext)
   {
   }

   public virtual new void RenderView(string viewName)
   {
       RenderView(viewName, null);
   }

   public virtual new void RenderView(string viewName, object viewData)
   {
       base.RenderView(viewName, viewData);
   }
}

The next thing is that the RenderView code is hard coded to use aspx view pages rather than using the configured view engine. I'm using the aspx view engine anyway, so it's not a killer for me, but even so it's very disappointing to see this.

Lastly, something which I do care about is the lack of a ComponentControllerFactory to allow us to substitute an alternative way of creating components. I am using the Windsor IoC container in my project and I would expect the RenderComponent method to call out to an abstract factory which would allow me to provide the components from Windsor. Luckily for me Jeremy Skinner has provided an alternative RenderComponent method in MVC contrib called RenderComponent2 which does just that. All I needed to do was register my Windsor container with his ComponentControllerBuilder:

// automatically register component controllers
container.Register(AllTypes
   .Of<ComponentController>()
   .FromAssembly(Assembly.GetExecutingAssembly())
   .Configure(c => c.LifeStyle.Transient.Named(c.Implementation.Name.ToLower())));

// set the component controller factory to the windsor container
ComponentControllerBuilder.Current.SetComponentControllerFactory(
   new IoCComponentControllerFactory(new WindsorDependencyResolver(container)));

Note the excellent new windsor mass registration API.

So in conclusion, it's a pretty poor show from the MVC team. I sincerely hope that a better implementation is given in CTP3.

Note: all this hackery is displayed in it's awfulness in my current project, sutekishop, which you can get the source of here:

http://code.google.com/p/sutekishop/

Saturday, April 12, 2008

Design Coding

Ken Egozi's shows this excellent YouTube artist called m0serious rapping about web site design. There are some great quotes here:

Friday, April 11, 2008

MVC Storefront

Rob Conery, the genius behind Subsonic, and now assimilated by the Borg, has just started a series of posts describing the process of building an eCommerce application using the MVC Framework. What's really cool about it is that he's soliciting input from some well known figures in the community as he evolves the project, so in the first screencast of the series he talked to Ayende and Steve Harman about some initial architectural choices including the repository pattern.

So far there are three episodes:

ASP.NET MVC: Introducing The MVC Storefront Series

ASP.NET MVC: MVC Storefront, Part 2

ASP.NET MVC: MVC Storefront, Part 3

And the source is available on Codeplex here.

The brilliant thing is, I'm currently working on an MVC eCommerce application as well. It's called sutekishop. It has a real first customer who's actually paying for it, but it's also open source. I've set up a Google code project here:

http://code.google.com/p/sutekishop/

I'm going to be keeping a very close eye on Rob's progress and incorporating as many of his ideas as possible into my project. So far it's very early days and I've only got a repository and the IoC container set up, but I'll be posting on my progress, so watch this space.

Thursday, April 10, 2008

Do Not Use Webhosting.uk.com

Disclaimer: I'm very reluctant to rubbish a company in public like this, but I think in this case the service has been so awful I feel a duty to warn others about them.

For the last few months I've been hosting a personal web site at webhosting.uk.com. I chose them after a friend recommended them for being relatively cheap and flexible. It sounded like a good deal, you could have as many sites as you liked within certain limits of disk space and bandwidth.

One morning I noticed the web site was down, but since it's not business related I didn't follow it up until later in the day. They provide an online technical support chat, so I fired it up and was soon told that there was a problem with some files being corrupted on the server but service would be resumed in six hours, i.e. later than night. The next morning the site was still unavailable. Once again I was given a figure of six hours and told not to worry because my data was safe. That evening the site was still unavailable. They continually failed to provide honest information about the state of the server. It took a further two days before they finally admitted that they had lost the drive and had no backups:

"1.The Windows OS got corrupt. That was the reason we decided to reinstall it. 2.This was a RAID server. To ensure that there is no data loss, we had multiple drives on the server wherein the web-date, MySQL & MS-SQL were backed up separately. This was done on the same server but on different drives. 3.While we were checking the server during OS re-installation, we also found that the primary hard-drive had faults on it and was not responding. Further evaluations and investigations revealed that the drive itself was faulty. Since this was a part of the RAID array, we had to deal with it very carefully. One single error would have resulted in the data getting wiped out. Inspite of all efforts, the data on the drive was not getting retrieved. That was the reason for the delays."

It's really hard to understand what happened from this garbled explanation. On the one hand they say they were using a RAID array, but then they contradict this by implying that different things were stored on different disks: "we had multiple drives on the server wherein the web-data, MySQL & MS-SQL were backed up separately. This was done on the same server but on different drives". That doesn't sound like my understanding of RAID.

But in any case, simply backing stuff up on a separate disk in the same box is a pretty crap strategy. Also simply doing database backups isn't sufficient. My site allowed my users to upload photos and these have all been lost. I've also lost the (somewhat ancient) code for the site since it was developed a long time ago on a long dead machine. Maybe I was naive to expect a host to back things up.

Since then the only compensation they've offered has been three month's of free hosting, even though I've probably lost at least £1000 in development time (to rewrite the software) plus the hours I wasted chasing them up plus the irretrievable loss of my user's photos. Free hosting is completely worthless from a company I've lost all trust with.

So, I'm now looking for a good hosting company. I'm quite interested in getting a dedicated server that I can look after myself. Any recommendations?

Monday, April 07, 2008

IoC Container Purse Fight

There's a great discussion of the problems and benefits of IoC containers on Serial Seb's blog: http://serialseb.blogspot.com/2008/04/ioc-container-is-not-carpet-it-floor.html

Thursday, April 03, 2008

Repository.GetById using LINQ Expression Syntax

A while ago I talked about using the IRepository<T> pattern with LINQ to SQL. One of the methods of my repository is GetById. The slight difficulty here is that we need to discover the primary key property of the (generated) type at runtime so we can't use a vanilla lambda expression in the Where clause. Before I used the DynamicQueriable helper library, but I've just re-written the function using an explicit expression tree which removes the need to reference the helper library.

public T GetById(int id)
{
    var itemParameter = Expression.Parameter(typeof(T), "item");

    var whereExpression = Expression.Lambda<Func<T, bool>>
        (
            Expression.Equal(
                Expression.Property(
                    itemParameter,
                    typeof(T).GetPrimaryKey().Name
                ),
                Expression.Constant(id)
            ),
            new ParameterExpression[] { itemParameter }
        );

    return dataContext.GetTable<T>().Where(whereExpression).Single();
}

Here is the extension method that finds the primary key:

public static PropertyInfo GetPrimaryKey(this Type entityType)
{
    foreach (PropertyInfo property in entityType.GetProperties())
    {
        ColumnAttribute[] attributes = (ColumnAttribute[])property.GetCustomAttributes(typeof(ColumnAttribute), true);
        if (attributes.Length == 1)
        {
            ColumnAttribute columnAttribute = attributes[0];
            if (columnAttribute.IsPrimaryKey)
            {
                if (property.PropertyType != typeof(int))
                {
                    throw new ApplicationException(string.Format("Primary key, '{0}', of type '{1}' is not int",
                        property.Name, entityType));
                }
                return property;
            }
        }
    }
    throw new ApplicationException(string.Format("No primary key defined for type {0}", entityType.Name));
}

Extension Properties for easy Reflection in C#

It's not generally considered good practice to define extension properties on object. But there's one scenario where I've found that it can be really nice. I've been copying the pattern of using anonymous types as dictionaries from the MVC Framework as described here by Eilon Lipton. This means you have to reflect over the anonymous type's properties to enumerate the dictionary. I've factored this reflection into an extension method for class:

public static IEnumerable<NameValue<string, object>> GetProperties(this object item)
{
    foreach (PropertyInfo property in item.GetType().GetProperties())
    {
        yield return new NameValue<string, object>(property.Name, () => property.GetValue(item, null));
    }
}

public class NameValue<TName, TValue>
{
    public TName Name { get; private set; }
    public TValue Value { get { return valueFunction(); } }

    Func<TValue> valueFunction;

    public NameValue(TName name, Func<TValue> valueFunction)
    {
        Name = name;
        this.valueFunction = valueFunction;
    }
}

Note that by using a lambda as the value in the NameValue class we defer actually accessing the value of the property until we need it.

Here's a test showing how you would use GetProperties:

[Test]
public void GetPropertiesShouldReturnThePropertiesOfAnAnonymousType()
{
    var item = new { Message = "Hello World", Number = 4 };

    Assert.AreEqual("Message", item.GetProperties().First().Name);
    Assert.AreEqual("Hello World", item.GetProperties().First().Value);
    Assert.AreEqual("Number", item.GetProperties().ElementAt(1).Name);
    Assert.AreEqual(4, item.GetProperties().ElementAt(1).Value);
}

Tuesday, April 01, 2008

Software Factories and Battery Programmers

batteryHen

A while back I had a client who was moving to a Web Service based ESB architecture. They had a number of Visual Basic 6 developers that they wanted to bring up to speed developing .NET web services and at the time I was getting interested in software factories, especially the P&P group's GAT. Their lead architect suggested that I write a software factory based on a standard web service architecture. Her intention was that she could get her VB devs to build web services without having to have a deep level of understanding about how they work. I had a great deal of fun building it, even though it was very early days for the GAT, and I learnt a lot about component based development by reading the P&P code. These days I look back on that job as one of my most enjoyable.

But how would I feel if I was one of those devs asked to use my GAT product? I'd hate it. Where's my joy? Everything I love about programming would have already been done by someone else. Not only that but I couldn't learn any lessons or move the architecture forward because it's all been locked down.

Every time I start a new project I tend to architect it in a different way. I learn new stuff all the time, recently it's been IoC containers, MVC frameworks and LINQ. If I was somehow constrained to do things the same way I would be far less productive and happy than I am (and I'm not that productive and happy in any case :P). The industry is too young, too fluid and too diverse to allow you to lock up your architecture without paying an awful price in lost opportunities.

I don't want to go into it now, but I don't like the architectural patterns imposed by a lot of the publicly released software factories from the P&P group. I think data transfer objects are a total waste of time in 90% of applications for a start. I would be mightily depressed if I had to work in a shop that had adopted them... oops, I did go into it...

And what about those legacy skilled VB developers. Well, you can guess... the software factory didn't allow them to quickly build web services without understanding the basics about .NET, XML and SOAP. They needed extensive training and hand holding. There's no replacement for skilled developers no matter what the tool venders tell you.

So Software Factories will go the same way as CASE tools, visual tools and code generators. After wasting lots of people's time and money they'll be cast into the void of software evolutionary dead ends.

Visual Tools: Marketing Dream, Programmer's Nightmare

I really enjoyed reading Secret Geek's (AKA Leon Bambrick) post today: Workflow software: I'm calling the bluff. Leon has a major gripe about workflow tools, especially the graphical tools that are their real selling point. Non-programmers love graphical tools. Why? Because code scares them, whereas the pretty pictures seem to make so much more sense. Non only that but, wonder of wonders, you can get business users to design the software. Wow, think of the savings of removing those expensive, scruffy awkward coders. Leon throws down a challenge:

"Show me a working 'business analyst' -- one, who is not now nor has ever been a coder -- who successfully designs 'business workflows' using an off the shelf tool, and who didn't require *any* expensive training, and who achieves their task in less time and with more precision than a coder. And who doesn't need to call technical support for help at the time.

Show me just one.

World wide.

I can wait. I give you one month. Nah, screw it. I give you eternity."

Somehow, I don't think he's going to see any challengers.

Visual tools make for great marketing. That's why so many companies spend so much money on Enterprise Workflow/Service Bus/Business Rule Engines. It's simple evolutionary psychology, Humans are evolved from fruit eating primates, we instinctively like anything with lumps of fruity colors. Code doesn't have that, it looks like something scary and mathematical. It's very hard to sell. But show some management type a colorful tool where you can simply drag and drop a few shapes to make a simple workflow and they're sold.

So what's the problem? It's simple: software is complex. Now that's not just a bit tricky, like sodoku say; it's seriously complex. Most visual tools give you little boxes that do an operation like a decision or maybe a calculation and those boxes are joined together with little lines. Hey, it's just like a programming language, except prettier. The problem is it's just like the simplest programming language. In fact it's a bit like the orginal BASIC:

BiztalkEqualsTRS80

I used to write very simple BASIC programs on my TRS-80 as a child. But even they sometimes had hundreds of lines of code. Imagine a picture with a hundred little boxes and several hundred little lines connecting them. You can only see the whole thing when it's zoomed too small to read any of the captions, and if you can read the captions you'll only see at best a dozen boxes.

The thing is, we've moved on a little since TRS-80 BASIC. Modern programming languages are fundamentally the distillation of fifty years of lessons learnt; pretty much every language innovation: loops, conditionals, stacks, functions, and all the technology of object oriented programming, not to mention the functional stuff, is there to help us manage the awesome complexity. There are hundreds of books and a million web pages written on the subject: algorithms, object orientation, design patterns, refactoring, testing, the list is endless. A good programmer has to work really hard to keep up with all this stuff. But the result is that with the current state of the art we can do a reasonable job at keeping this horrendous complexity under control.

If you use a visual programming tool, you're throwing all this away. You cannot write anything other than a simple demo program with a visual tool. If you try you will fail.

There's one place where I think visual tools succeed and that's when they're used to represent static structure. I would much rather look at a data model in SQL Server's Database Diagram tool than trying to grep a long list of create table statements, and of course, it's far easier to work on a user interface with a graphical designer than by hand coding the construction and mapping of loads of objects. I actually rather like the class designer in Visual Studio. But I will never use a graphical tool to create program flow or logic.