Sunday, 28 September 2008

Keeping code clean - Decorators for Error Handling?

I read a review a few days ago of the new book by Robert C Martin (Uncle Bob) 'Clean Code'. I'm going to order a copy as soon as I clear a couple of books from my current reading list backlog as it sounds interesting and the Uncle Bob blog on Object Mentor is one that I always enjoy to read. One of the things that stuck in my mind from the review was that the 'Do one thing' principle applies even to error handling.

Hmmm, if you see the example in the review (I don't know if its' from the book) then this is shown as not evaluating the exception and acting according to its' type, but rather just logging it. This has been nagging in my mind since I read it. Its' not that I disagree with the example, using exceptions for control of flow has always struck me as being a thoroughly poor practice in every place I've seen it done. It was more the idea that perhaps I shouldn't even have the try-catch block around my code in the first place. Now I know that the where's and when's of exception handling (let alone the how's and why's - any of Kiplings six honest serving men in fact) are a very contested country and I'm certainly not positing what follows as 'the answer', just an idea.

What struck me was that I could use the decorator pattern to implement my error handling. For example I have an interface:

public interface ICandidateRepository
{
Candidate GetCandidate(Guid candidateId);

Candidate RegisterNewCandidate();

void SaveCandidate(Candidate candidate);

List<Candidate> FindCandidates(ICandidateCriteria criteria);

}

I already have a concrete class that implements this interface and uses NHibernate to perform the functions that are described. Instead of wrapping these calls in try-catch blocks I can create a new concrete class that implements this interface and looks like this:

public class CandidateRepositoryExceptionDecorator : ICandidateRepository
{
private readonly ICandidateRepository _nestedCandidateRepository;
private ILogger _logger;

public ILogger Logger
{
get { return _logger ?? NullLogger.Instance; }
set { _logger = value; }
}

public CandidateRepositoryExceptionDecorator(ICandidateRepository candidateRepository)
{
_nestedCandidateRepository = candidateRepository;
}

public Candidate GetCandidate(Guid candidateId)
{
try
{
return _nestedCandidateRepository.GetCandidate(candidateId);
}
catch (Exception ex)
{
_logger.ErrorFormat(ex, "Exception when calling GetCandidate({0}).", candidateId);
throw;
}
}

// ... etc ...

}

I use my DI framework of choice to get the parameters into the constructor and to organise the nesting of my objects. In my case this is with the Windsor container. The components section is left like this:

<components>
<component id="candidateRepositoryErrorHandler" service="Semeosis.Examinations.Model.Interfaces.ICandidateRepository, Semeosis.Examinations.Model.Interfaces" type="Semeosis.Examinations.Model.Repositories.Decorators.CandidateRepositoryExceptionDecorator, Semeosis.Examinations.Model.Repositories.Decorators" />
<component id="candidateRepository" service="Semeosis.Examinations.Model.Interfaces.ICandidateRepository, Semeosis.Examinations.Model.Interfaces" type="Semeosis.Examinations.Model.Repositories.NHibernate.CandidateRepository, Semeosis.Examinations.Model.Repositories.NHibernate" />
</components>

The order in which the components are listed determines the order in which the container chains the objects. See this post by Oren for more info.

The upshot of this is that when I call:

ICandidateRepository repository = container.Resolve<ICandidateRepository>();

I get an instance of my CandidateRepositoryExceptionDecorator and this contains my CandidateRepository class from my NHibernate repositories project.

Now my concerns are separated and I can keep the functions that deal with the creational and persistence concerns separate from the error handling concerns. If in the future I need to change the way that my exception handling is manager, or I need to perform other actions than just logging when an exception is logged then I can very easily extend this code. Also unit testing this is incredibly trivial using mocking, whilst also reducing the number of tests on the functions that actually 'do the work'. Separation of concerns in one layer helps keep things clean and tidy across many other layers of the onion! I guess that's why TDD can have such a beneficial effect on model design - but the benefits can be two way.

Testing DateTime Type Properties for Value Equality in Integration Tests

I've just been writing some integration tests to ensure that some Repositories I'm writing work with NHibernate properly, basically ensuring that the mappings do what I want. The Repository classes in question use the latest release of NHibernate (2.0.0.GA) for their implementation and I'm using MbUnit for my integration tests.

To try and save on the number of asserts that I have to write I thought that I'd try to use the Assert.AreValueEqual method that MbUnit provides. This allows me to write this in my test:

foreach (PropertyInfo propertyInfo in typeof(Candidate).GetProperties())
{
Assert.AreValueEqual(propertyInfo,expected,actual, null);
}

The context for this test is that I'm persisting a copy of a new Candidate object to the database (using NHibernate, but not my repository) which exposes a property, RegistrationDate, of the type ?DateTime. When this property is cycled through to the Assert always fails. Initially this puzzled me as the two DateTime instances appeared to be the same. A quick look at the DateTime.Equals(DateTime) method in reflector soon revealed that when this operation is called it is the InternalTicks property that is the subject of the comparison:

return (this.InternalTicks == value.InternalTicks);

When I get the DateTime back from the database this is not as precise as it was originally in the world of the CLR. The expected (original) value is 633581595292333682 whilst the actual (retrieved) value is 633581595290000000. This isn't enough of a difference to be significant for my purposes, as the ToString() representations are Equal and I don't need a level of accuracy beyond days, let alone fractions of a second.

I figure my options here are:

  1. Don't use Assert.AreValueEqual and hand write each Assertion as an Assert.AreEqual instead;
  2. Store the DateTime in the database as the value of the InternalTicks rather than the DateTime value itself. The obvious problem I can see with this is that any extraction, such as to a reporting database, would become more problematic if this was done. I figure there are times when testing should inform design, but this is clearly not one of them!
  3. Isolate NullableDateTime type properties and deal with these differently.

By changing the code a little I am able to isolate DateTime properties and deal with these using the ToString() method like this:

Type NullableDateTimeType = Type.GetType("System.Nullable`1[[System.DateTime, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]");
foreach (PropertyInfo propertyInfo in typeof(Candidate).GetProperties())
{
if (propertyInfo.PropertyType == NullableDateTimeType)
{
DateTime expectedDateTime = (DateTime)propertyInfo.GetValue(expected, null);
DateTime actualDateTime = (DateTime)propertyInfo.GetValue(expected, null);
Assert.AreEqual(expectedDateTime.ToString(), actualDateTime.ToString(), "The expected RegistrationDate is not equal to the actual RegistrationDate.");
}
else
{
Assert.AreValueEqual(propertyInfo, expected, actual, null);
}
}

I'm not too sure how much coding I've saved myself with this, but I figure that as the number of properties involved increases it will reduce maintenance. If anyone out there has a better solution (doing this at gone 2 in the morning makes me think that there probably is a better solution) then please feel free to suggest it.

Tuesday, 23 September 2008

Uninstalling AVG Anti-Virus SBS Edition broke my MS Exchange

The licence for my AVG Small Business Server 2003 Edition recently came to an end and after looking around I decided that rather than renew it I'd replace it with Microsoft's new Forefront products. This is probably vast overkill, but I figured it'd be interesting to see how it all works and I generally prefer vast overkill anyway.

What I discovered was that it's quite an involved process to get all the various pieces installed and working (ever the way with 'Enterprise software') so I uninstalled the AVG software and for a little while now have been going without protection on this server. Yeah, yeah, bad idea I know.

Shortly after uninstalling I found that Outlook clients couldn't connect to the Exchange server on this box. Not only that, but people were getting bounce emails saying that their messages couldn't be delivered. Thankfully I route all emails through another external email server (with its' own anti-virus and spam filtering) before having them forwarded through to my internal Exchange server so I wasn't actually losing the emails, but clearly something was wrong. I tried the old 'restart the box' trick but even this didn't work so I turned my attention to the Event logs and started to look for any errors of warning. What I found, amongst others not seemingly relevant, were the following:

Event Type: Error
Event Source: MSExchangeFBPublish
Event Category: General
Event ID: 8197
Date: 19/09/2008
Time: 11:18:36
User: N/A
Computer: The server name
Description:
Error initializing session for virtual machine SERVER01. The error number is 0x8004011d. Make sure Microsoft Exchange Store is running.

Event Type: Information
Event Source: EXCDO
Event Category: General
Event ID: 8196
Date: 19/09/2008
Time: 11:17:13
User: N/A
Computer: The server name
Description:
Calendaring agent is stopping successfully.

Event Type: Information
Event Source: EXOLEDB
Event Category: General
Event ID: 101
Date: 19/09/2008
Time: 11:17:13
User: N/A
Computer: The server name
Description:
Microsoft Exchange OLEDB has successfully shutdown.

Event Type: Error
Event Source: MSExchangeIS
Event Category: General
Event ID: 9564
Date: 19/09/2008
Time: 11:17:12
User: N/A
Computer: The server name
Description:
Error 0x80004005 starting the Microsoft Exchange Information Store.
Failed to init VSERVER.

Event Type: Error
Event Source: MSExchangeIS
Event Category: Virus Scanning
Event ID: 9581
Date: 19/09/2008
Time: 11:17:12
User: N/A
Computer: The server name
Description:
Error code -2147467259 returned from virus scanner initialization routine. Virus scanner was not loaded.

What I took from these was that due to my uninstalling the anti-virus software Exchange was now broken because the Microsoft Exchange Information Store couldn't now start.

A quick google on 'Error 0x80004005 starting the Microsoft Exchange Information Store' led me to an Experts-Exchange post, and scrolling to the bottom informed me about a registry key: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\MSExchangeIS\VirusScan. I changed this, as suggested, so that Enabled is set to 0, restarted the server, waited a few minutes, started Outlook and held my breath. Very quickly emails started to flood in to their relevant folders.

Now all I have to do is get the Forefront products up and running nicely, and then probably upgrade my infrastructure to Server 2008 and Exchange 2008 (following the new branch office configuration).

ASP.NET MVC - If it feels this right it can't be wrong!

Having had a few days leave from work I've spent most of my evenings playing with the not-so new MVC framework. It's been great to spend some focused time playing with this new toy for web development from Microsoft. One thing that I've noticed is how nicely and quickly you can start to put together powerful, enterprise happy software with it. My starting point has been a model (a bunch of POCOs based around the educational assessment domain, which I know well) using NHibernate for persistence, Windsor for a DI framework (though not for the controllers yet), MBUnit and RhinoMocks for unit testing, and the latest (5) release of the MVC framework. After getting some simple stories completed (add a candidate, edit a candidate, register a candidate for an assessment) I wanted to try and improve the user experience by getting some Ajax into the Views. I've had a play with using Scriptaculous and JQuery with the MVC framework during brief forays in the past, so this time I thought I'd just use the default MS stuff that ships with it.

One example of the kind of implicit wiring that the framework deals with you that I found really neat was this. I have a view that lists candidates based on a search (I hope to blog about that before long).

<%
foreach (Candidate candidate in ViewData.Model as List<Candidate>)
{%>
<tr>
<td><%=Ajax.ActionLink("View", "ViewDetail", "Candidate", candidate, new AjaxOptions { UpdateTargetId = "CandidateDetail" })%></td>
<td><%=Ajax.ActionLink("Edit","EditDetail","Candidate", candidate, new AjaxOptions{ UpdateTargetId = "CandidateDetail"}) %></td>
<td><%=Html.Encode(candidate.Id.ToString())%></td>
<td><%=Html.Encode(candidate.Name.FullName)%></td>
</tr>
<%
}%>

Note the use of the Ajax.ActionLink method here. This will update my CandidateDetail div with the results of the Ajax call. The call itself will be to the ViewDetail action of the CandidateController class, and the properties of the Candidate object for the row will be available to this action. The neat thing for me is that in the action if I request just an id argument then this is automagically wired up to the Id property of the Candidate object for me!

[AcceptVerbs("POST")]
public ActionResult ViewDetail(Guid id)
{
ICandidateRepository candidateRepository = MvcApplication.WindsorContainer.Resolve<ICandidateRepository>();
Candidate candidate = candidateRepository.GetCandidate(id);
return View("Detail", candidate);
}

As you can see, the code above has one argument that accepts a Guid and is called id. The framework, following convention (love that), realises I mean the id of the candidate object and passes it into the method. Neat huh! I then get the appropriate candidate object from my repository and then return the detail view (an ascx control) passing the retrieved candidate object in. This control will then be rendered into the div originally specified (CandidateDetail).

This is just one example of how easy it can be to get this framework working for you. I'm really, really liking working with all this new MVC goodness, it just feels so, right!

Monday, 1 September 2008

Google Chrome

Google this and you will find a slew of links talking about a new open source browser that Google are developing.

Check this link for a scanned in copy of a comic book that is apparently being sent out to various chosen people/organisations. Also this link (same site) for a description.

It looks interesting, a bit more competition in this space should be good. I just hope that they implement the DOM and Javascript properly (unlike [all] other well known implementations). Which makes me wonder if there will be a Flash or Silverlight add-in for it (and if these will be treated with parity).

My favourite feature from those discussed is that there will be a task manager where users will be able to view the plugins and web pages active in the browser, and the resources that they are responsible for consuming.

Google's power in the web-space is already significant and ownership of a browser would no doubt increase this, open source or not. Hmmmm... guess I'll get back to playing with AppEngine and learning Python!

Tuesday, 26 August 2008

Getting Ubuntu 'Hardy Heron' on to a VM - Part 2

New day, and armed with the download of the Desktop version of 'Hardy Heron' I'm installing it on to a Virtual PC VM following the instructions that I found here: http://blogs.technet.com/seanearp/archive/2008/05/13/installing-ubuntu-8-04-hardy-heron-in-virtual-pc-2007.aspx

After reaching the point where I have started the install on the desktop - so far so good.

installing linux on virtual pc 1

installing linux on virtual pc 2

It already is looking far more promising.

Well I've gotten through now as far as altering the audio, and all good so far! I'm holding my breath whilst it restarts (not literally - its' not that quick).

Well, I just heard some bongo like sounding noise immediately before being invited to login (and again after getting the details wrong first time).

installing linux on virtual pc success

Success!

The moral to this seems to be to use the desktop version instead of the server version. If anyone has got the server version on an MS flavour VM then I'd love to hear about it.

Next will be following the instructions to get the screen size right, templating it, and then getting Oracle installed.

Saturday, 23 August 2008

Getting Ubuntu 'Hardy Heron' on to a VM - An Unhappy Saga

I've been meaning to dip my toes into the Linux water for a while now - my last exposure being a brief one about ten years ago at Uni. Yesterday evening I thought I'd actually do it. My particular motivation in this case was to run Oracle, something I'm working with a lot at work, and I figured I might as well run it on Linux as not (although we run it on Windows at work).

So, with my Ubuntu Hardy Heron downloaded, and a nice enough VM fresh and clean (2GB RAM, 16GB HDD) I naively thought I'd have it done before bed. Sadly I was wrong :(

Problem number 1 was "An unrecoverable processor error has been encountered.".

HardyHeronVirtualPCError1

After a lot of Googling I found quite a few posts on this. A number of them recommended installing it in Safe Graphics Mode. When I pressed F4 though I only got one option, Normal, so that wasn't going to help me I figured. In the end the article that I followed was this one: http://www.corey-m.com/blog/?p=326.

This recommended that I press F6 and alter the Boot Options line by adding noreplace-paravirt to the end of it (well, just before the --). This was to be done on the initial install, and then again after this but using the 'Rescue a broken system' option this time. Well I did this and then from the Shell I tried to execute the 'apt-get update' command.

This brought about problem 2.

linuxvirtualpcproblem2

Basically, a bunch of 'Could not resolve' messages. Hmmm, at this point I went to bed. This evening though when I got in from work I thought I'd have another crack at it. I tried pinging www.google.com with no joy, but then tried pinging it by IP address and that succeeded. Clearly my issue was connected with the resolution of domain names. A bit more googling later and I found this posting: https://bugs.launchpad.net/ubuntu/+source/resolvconf/+bug/177767. Although not specifically for my situation, it seemed to present a resolution for something close enough so I figured that I'd give it a go.

touch /etc/resolv.conf
dhclient eth0

Having entered the above the resolv.conf file was created, google could be pinged by name and best of all the apt-get update command worked.

This working I returned to the aticle I was following originally (http://www.corey-m.com/blog/?p=326) and tried the next instruction: apt-get install linux-386.

This brought me to problem 3. A series of 'dependency problems' with a variety of Linux packages were reported apparently because they were 'not configured yet', leading to a message that 'Errors were encountered while processing'.

linuxvirtualpcproblem3

Day 3... still no further...

I tried various tricks to get the packages to be configured, in particular reading and following the advice in this 'http://ubuntuforums.org/showthread.php?t=186672' post. But no matter what I tried, still no success.

So I gave up (for now at least) and thought I'd try a different tack - install Windows Server 2005 R2 and get it working on that. I remember seeing a blog post that said that Hardy installs easily onto a Virtual Server vm.

Installing Virtual Server proved to be not too much trouble. I'm running Vista Enterprise and I needed to install the CGI feature (I already had the IIS 6 Compatibility stuff), the Windows Authentication feature. This allowed the exe to run (for the admin interface) and got rid of the annonying 'An error occurred accessing the website application data folder.' message. Just remember to run the Admin interface as an Administrator (and make sure you don't have Anonymous Authentication enabled for the site).

Virtual Server 2005R2 installed and working, I created a new VM and began the install of Hardy Heron on to it. I found I still had to use the noreplace-paravirt option to get it the install to run. One install later and a screen I've unhappily seen before appeared.

linuxvirtualpcproblem4

I'd seen this screen already, when trying to let an install of Ubuntu boot.

Day 4: This is not an experience that I'm enjoying! I'm downloading the latest version of Hardy Heron, but this time the Desktop version rather than the Server version. I left my computer downloading it last night but Vista decided to restart after updating itself with only about 20MB left to go, so I've had to restart the download today. I feel as if this whole process is cursed! I have to drive to Liverpool now, so I'll post later when I've had a chance to see if this has made any difference.