Wednesday, June 21, 2006

The Power of Predicates

I ran up against a problem I'd not encountered before today - how to use the Find method on a generic List. The MSDN documentation is less than enlightening, but I found an excellent article entitled "Using generics to manage a collection of objects" byAmirthalingam Prasanna on simple-talk.com.

Amirthalingam covers the subject in detail, but I thought I'd share my reference implementation (and put it up somewhere that I can find it when I forget how to do this!). Purple elipses ( ... ) indicate where the finished code continues.

We'll implement a simple C# console application to start with to act as the framework for our reference implementation.
using System;
using System.Collections.Generic;
using System.Text;

namespace List_Find_Predicate_Test
{
class Program
{
static void Main(string[] args)
{
}
}
}
Next, let's define a "complex" class against a List of which we will search - we'll do this as a private inner class within our framework:
...
class Program
{
private enum Gender
{
Male,
Female
}

private class Criteria
{
public string Field;
public Type DataType;

public Criteria(string theField, Type theDataType)
{
this.Field = theField;
this.DataType = theDataType;
}
}
...
}
...
You'll notice I've spiced things up with a custom enumeration used within the Criteria class. Next, let's add some code to the Main method to build us a list of criteria objects:
...
static void Main(string[] args)
{
List<Criteria> critList = new List<Criteria>();
critList.Add(new Criteria("Name", typeof(System.String)));
critList.Add(new Criteria("Age", typeof(System.Int16)));
critList.Add(new Criteria("Gender", typeof(Gender)));

Console.WriteLine("List has {0} entries...", critList.Count);

// TODO: Search the list
...
}
...
Simple enough so far. The complexity happens in providing a mechanism to let the List.Find method operate - this is where Predicate classes come in. Predicates are analagous to Delegates - they effectively implement a call-back to a method that performs the comparison, and it is this call-back that the Find method uses to find matching elements in the List.

Let's add a quick search of the List, and get the type assigned to the "Name" criteria:
...
static void Main(string[] args)
{
...
// Search the list
Criteria crit = FindCriteriaByName(critList, "Name");
Console.WriteLine("Name criteria has type {0}", crit.DataType.Name);

// TODO: Search without having to use a helper method
...
}

// TODO: Implement FindCriteriaByName
...
OK - that was easy enough - just your common-or-garden-variety top-down programming so far. But now we get to the meat of the issue - the implementation of the FindCriteriaByName method - and this is where Predicates are used.

The key to Predicates is that they reference a class - in this case a class that is dedicated to filtering a List. We'll implement this as another private class within the program framework. This filter class is as simple as they come, taking a string parameter for its constructor, and exposing just one method FilterByField.
...
class Program
{
...
private class CriteriaFieldFilter
{
private string criteriaField;

public CriteriaFieldFilter(string fieldName)
{
criteriaField = fieldName;
}

public bool FilterByField(Criteria crit)
{
return (crit.Field == criteriaField);
}
}
...
}
...
You'll notice that the critical FilterByField method accepts a Criteria object as its parameter - when we call this class through a Predicate, this is the method that will be used to perform the filtering. So we can now finally implement the filter method:
...
class Program
{
...
// Implement FindCriteriaByName
private static Criteria FindCriteriaByName(List<Criteria> theList, string theName)
{
CriteriaFieldFilter searchFilter = new CriteriaFieldFilter(theName);
Predicate<Criteria> searchPredicate = new Predicate<Criteria>(searchFilter.FilterByField);
Criteria crit = theList.Find(searchPredicate);
return crit;
}
...
}
...
So our filtermethod starts by instantiating an instance of our filter class tailored with the field name passed in the theName parameter. The Predicate is then created against a pointer to the FilterByField method of that instance, and in turn that Predicate is used with the List.Find method to return the matching entry.

But is there a more compact way rather than having to implement the helper method at all? Of course there is! We just compact the code into an in-line function, thus:
...
static void Main(string[] args)
{
...
// Search without having to use a helper method
crit = critList.Find(new Predicate<Criteria>((new CriteriaFieldFilter("Gender")).FilterByField));
Console.WriteLine("Gender criteria has type {0}", crit.DataType.Name);
...
}
...
Rather harder on the eye, but more compact. I'd imagine that something could be done with Anonymous classes/methods to simplify this further, but that's a topic of research for another time.

Phew! A complex topic for just performing a Find in a List, but it does allow us to write any kind of matching algorithm we like working against just a single T instance and they use that matching algorithm to work with an entire List - that's the power of Predicates.

Thursday, June 15, 2006

Visual Studio Managed Code Analysis (FxCop) : FAQ: Why does FxCop warn against catch(Exception)? [Nick Guerrera]

In his recent posting titled "FAQ: Why does FxCop warn against catch(Exception)?":, Nick Guerrera does a great job of explaining best practice in exception handling.

I’ve heard a lot of arguments against DoNotCatchGeneralExceptionTypes, but they generally boil down to one or both of the following:
  • “If I call an API which doesn’t document which exceptions it can throw, then I have no choice but to catch all possible exceptions!”

  • “My application needs to be robust; it can’t crash just because of an exception that I forgot to handle!”
Well worth reading and thinking about how you code your exception handling routines - I know for one I use catch (Exception e) w-a-y too much!

Thursday, June 01, 2006

SOA, Autonomy and Caching

In the latest posting in his blog, Clemens Vasters gives an excellent reminder about what SOA really means for a developer or architect, and of some of its history.

But it's the pragmatism that Service Autonomy doesn't really matter under the hood because behind the service boundary is a private domain and "none of your business" to the outside world.

Finally, he makes some good points about caching, and particularly about passing forward cache validity information along with the data so that a client of a service can make an intelligent caching decision.

All well worth keeping in mind when, as I, you're building a large distributed system - find it here.

Jay Kimble -- The Dev Theologian : How to Add Atlas to an existing site (For Brendan)

Getting started with a new technology is one thing, but retro-fitting it onto an existing project is quite another.

I blogged previously on doing so for LINQ, but hadn't had the opportunity to work out the details for one of the other new technologies I'm using, ATLAS.

Thanks to an excellent posting by Jay Kimble, I don't have to!

In his post "How to Add Atlas to an existing site (For Brendan)", he details step-by-step what's needed to add ATLAS support to an existing ASP.Net web application.

Excellent!