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!