Showing posts with label Patterns. Show all posts
Showing posts with label Patterns. Show all posts

Thursday, October 25, 2007

Specifications versus validators

Joe posed a great question on my recent entity validation post:

I question the term Validator in relation to DDD.  Since the operation of the Validator seems to be a simple predicate based on business rule shouldn't the term Specification [Evans Pg227] be used instead?

On the surface, it would seem that validation does similar actions as specifications, namely that it performs a set of boolean operations to determine if an object matches or not.

For those unfamiliar with the Specification pattern, it provides a succinct yet powerful mechanism to match an object against a simple rule.  For example, let's look at an expanded version of the original Order class on that post:

public class Order
{
    public int Id { get; set; }
    public string Customer { get; set; }
    public decimal Total { get; set; }
}

A Specification class is fairly simple, it only has one method that takes the entity as an argument:

public interface ISpecification<T>
{
    bool IsSatisfiedBy(T entity);
}

I can then create specific specifications based on user needs.  Let's say the business wants to find orders greater than a certain total, but the total can change.  Here's specification for that:

public class OrderTotalSpec : ISpecification<Order>
{
    private readonly decimal _minTotal;

    public OrderTotalSpec(decimal minTotal)
    {
        _minTotal = minTotal;
    }

    public bool IsSatisfiedBy(Order entity)
    {
        return entity.Total >= _minTotal;
    }
}

Specs by themselves aren't that useful, but combined with the Composite pattern, their usefulness really shines:

public class AndSpec<T> : ISpecification<T>
{
    private readonly List<ISpecification<T>> _augends = new List<ISpecification<T>>();

    public AndSpec(ISpecification<T> augend1, ISpecification<T> augend2) 
    {
        _augends.Add(augend1);
        _augends.Add(augend2);
    }

    public AndSpec(IEnumerable<ISpecification<T>> augends)
    {
        _augends.AddRange(augends);
    }

    public void Add(T augend)
    {
        _augends.Add(augend);
    }

    public bool IsSatisfiedBy(T entity)
    {
        bool isSatisfied = true;
        foreach (var augend in _augends)
        {
            isSatisfied &= augend.IsSatisfiedBy(entity);
        }
        return isSatisfied;
    }
}

Adding an "OrSpec" and a "NotSpec" allows me to compose some arbitrarily complex specifications, which would otherwise clutter up my repository if I had to make a single search method per combination:

OrderRepository repo = new OrderRepository();
var joesOrders = repo.FindBy(
    new AndSpec(
        new OrderTotalSpec(100.0m),
        new NameStartsWithSpec("Joe")
    ));

Given the Specification pattern (fleshed out into excruciating detail), why can't I compose validation into a set of specifications?  Let's compare and contrast the two:

Specification

  • Matches a single aspect on a single entity
  • Performs positive matching (i.e., return true if it matches)
  • Executed against a repository or a collection
  • Can be composed into an arbitrarily complex search context, where a multitude of specifications compose one search context
  • "I'm looking for something"

Validator

  • Matches as many aspects as needed on a single entity
  • Performs negative matching (i.e., returns false if it matches)
  • Executed against a single entity
  • Is intentionally not composable, a single validator object represents a single validation context
  • "I'm validating this"

So although validation and specifications are doing similar boolean operations internally, they have very different contexts on which they are applied.  Keeping these separate ensures that your validation concerns don't bleed over into your searching concerns.

Wednesday, October 24, 2007

Entity validation with visitors and extension methods

On the Yahoo ALT.NET group, an interesting conversation sprung up around the topic of validation.  Entity validation can be a tricky beast, as validation rules typically depend on the context of the operation (persistence, business rules, etc.).

In complex scenarios, validation usually winds up using the Visitor pattern, but that pattern can be slightly convoluted to use from client code.  With extension methods in C# 3.0, the Visitor pattern can be made a little easier.

Some simple validation

In our fictional e-commerce application, we have a simple Order object.  Right now, all it contains are an identifier and the customer's name that placed the order:

public class Order
{
    public int Id { get; set; }
    public string Customer { get; set; }
}

Nothing too fancy, but now the business owner comes along and requests some validation rules.  Orders need to have an ID and a customer to be valid for persistence.  That's not too hard, I can just add a couple of methods to the Order class to accomplish this.

The other requirement is to have a list of broken rules in case the object isn't valid, so the end user can fix any issues.  Here's what we came up with:

public class Order
{
    public int Id { get; set; }
    public string Customer { get; set; }

    public bool IsValid()
    {
        return BrokenRules().Count() > 0;
    }

    public IEnumerable<string> BrokenRules()
    {
        if (Id < 0)
            yield return "Id cannot be less than 0.";

        if (string.IsNullOrEmpty(Customer))
            yield return "Must include a customer.";

        yield break;
    }
}

Still fairly simple, though I'm starting to bleed other concerns into my entity class, such as persistence validation.  I'd rather not have persistence concerns mixed in with my domain model, it should be another concern altogether.

Using validators

Right now I have one context for validation, but what happens when the business owner requests display validation?  In addition to that, my business owner now has a black list of customers she won't sell to, so now I need to have a black list validation, but that's really separate from display or persistence validation.  I don't want to keep adding these different validation rules to Order, as some rules are only valid in certain contexts.

One common solution is to use a validation class together with the Visitor pattern to validate arbitrary business/infrastructure rules.  First, I'll need to define a generic validation interface, as I have lots of entity classes that need validation (Order, Quote, Cart, etc.):

public interface IValidator<T>
{
    bool IsValid(T entity);
    IEnumerable<string> BrokenRules(T entity);
}

Some example validators might be "OrderPersistenceValidator : IValidator<Order>", or "CustomerBlacklistValidator : IValidator<Customer>", etc.  With this interface in place, I modify the Order class to use the Visitor pattern.  The Visitor will be the Validator, and the Visitee will be the entity class:

public interface IValidatable<T>
{
    bool Validate(IValidator<T> validator, out IEnumerable<string> brokenRules);
}

public class Order : IValidatable<Order>
{
    public int Id { get; set; }
    public string Customer { get; set; }

    public bool Validate(IValidator<Order> validator, out IEnumerable<string> brokenRules)
    {
        brokenRules = validator.BrokenRules(this);
        return validator.IsValid(this);
    }
}

I also created the "IValidatable" interface so I can keep track of what can be validated and what can't.  The original validation logic that was in Order is now pulled out to a separate class:

public class OrderPersistenceValidator : IValidator<Order>
{
    public bool IsValid(Order entity)
    {
        return BrokenRules(entity).Count() > 0;
    }

    public IEnumerable<string> BrokenRules(Order entity)
    {
        if (entity.Id < 0)
            yield return "Id cannot be less than 0.";

        if (string.IsNullOrEmpty(entity.Customer))
            yield return "Must include a customer.";

        yield break;
    }
}

This class can now be in a completely different namespace or assembly, and now my validation logic is completely separate from my entities.

Extension method mixins

Client code is a little ugly with the Visitor pattern:

Order order = new Order();
OrderPersistenceValidator validator = new OrderPersistenceValidator();

IEnumerable<string> brokenRules;
bool isValid = order.Validate(validator, out brokenRules);

It still seems a little strange to have to know about the correct validator to use.  Elton wrote about a nice trick with Visitor and extension methods that I could use here.  I can use an extension method for the Order type to wrap the creation of the validator class:

public static bool ValidatePersistence(this Order entity, out IEnumerable<string> brokenRules)
{
    IValidator<Order> validator = new OrderPersistenceValidator();

    return entity.Validate(validator, brokenRules);
}

Now my client code is a little more bearable:

Order order = new Order();

IEnumerable<string> brokenRules;
bool isValid = order.ValidatePersistence(out brokenRules);

My Order class doesn't have any persistence validation logic, but with extension methods, I can make the client code unaware of which specific Validation class it needs.

A generic solution

Taking this one step further, I can use a Registry to register validators based on types, and create a more generic extension method that relies on constraints:

public class Validator
{
    private static Dictionary<Type, object> _validators = new Dictionary<Type, object>();

    public static void RegisterValidatorFor<T>(T entity, IValidator<T> validator)
        where T : IValidatable<T>
    {
        _validators.Add(entity.GetType(), validator);
    }

    public static IValidator<T> GetValidatorFor<T>(T entity)
        where T : IValidatable<T>
    {
        return _validators[entity.GetType()] as IValidator<T>;
    }

    public static bool Validate<T>(this T entity, out IEnumerable<string> brokenRules)
        where T : IValidatable<T>
    {
        IValidator<T> validator = Validator.GetValidatorFor(entity);

        return entity.Validate(validator, out brokenRules);
    }
}

Now I can use the extension method on any type that implements IValidatable<T>, including my Order, Customer, and Quote classes.  In my app startup code, I'll register all the appropriate validators needed.  If types use more than one validator, I can modify my registry to include some extra location information.  Typically, I'll keep all of this information in my IoC container so it can all get wired up automatically.

Visitor patterns are useful when they're really needed, as in the case of entity validation, but can be overkill sometimes.  With extension methods in C# 3.0, I can remove some of the difficulties that Visitor pattern introduces.

Friday, October 19, 2007

Dependency Breaking Techniques: Inline Static Class

Often times I run into a class that has a dependency not on a Singleton, but a static class.  When refactoring away from a Singleton, a common approach is to use Inline Singleton.  With static classes, a slightly different approach needs to be taken because client code isn't working with an instance of a type, but rather static methods on the type itself.

Dependency breaking techniques are used to get legacy code under test.  The goal isn't necessarily to break all client dependencies out, but just the one I'm modifying to get under test.  I'm not interested changing any of the other clients that may use this static class.  Since nothing is under test, it's too risky to make non-backwards compatible changes.

The pattern

Code needs access to a method or property but doesn't need a global point of access to it.

Move Static's features to instance methods of that type.

Motivation

Helper methods tend to congregate into static classes with static methods.  Over time, the responsibility grows for the static class until it becomes a dumping ground to any behavior that seems relevant to the name.  The name of the static class usually is post-fixed by "Helper", "Manager", "Utility", or other generic and obtuse names.

Eventually, this static class will have opaque dependencies of its own, where callers don't know what's happening behind the scenes when those helper methods are called.  This can wreak havoc with unit testing, especially when trying to add tests to legacy code.

Mechanics

  1. Find the static method in the calling class and use Extract Interface to extract an interface that contains only the static method being called in the client code.
  2. Make the static class explicitly implement the new extracted interface.  The static class should have two methods with identical signatures, one a static method, one an explicitly implemented interface method.
  3. Use Move Method to move the logic from the static method to the instance method.
  4. Use Hide Delegate to delegate the static method calls to the use the instance method instead.
  5. Compile and test.
  6. Modify Client code using the static Operation method to instantiate an IStatic instance and call the interface Operation method.
  7. Compile and test.
  8. Use Extract Parameter to pass in the IStatic instance to the Client method.  If IStatic is a primal dependency, extract the parameter to a constructor argument and set the variable to a local field.
  9. Compile and test.

Example

In our e-commerce system, one of the pages the user is presented with is a payments page.  It is in this page that the user decides how they want to pay for their order, whether it's credit card, invoice, financing, etc.

Not all payment types should be displayed for all carts, and there is some complex business logic that determines who sees what payment types.  There are several payment filtering strategies to encapsulate this business logic, and one type uses the user's profile to filter the payments.  Here's the strategy class:

public class AccountFilter
{
    private readonly string[] _paymentTypes;

    public AccountFilter(string[] paymentTypes)
    {
        _paymentTypes = paymentTypes;
    }

    public void AddPaymentOptions(ShoppingCart cart)
    {
        IPayment payment = ProfileManager.FindPaymentByType(_paymentTypes);

        if ((payment != null) &&
            (! string.IsNullOrEmpty(cart.AccountNumber)))
        {
            cart.PaymentFilters.Add(payment);
        }
    }

}

The business has a new requirement for us: Payment types should not be filtered using the user's profile for existing quotes.  In our system, customers can save their cart as a "quote", so that the unit cost information can be "locked" for a set amount of time.  Enabling this change requires us to change the AccountFilter class.

Being a legacy code system, the AccountFilter class has no tests defined on it.  It's our goal to make the change and add tests to verify the new requirements, and that's all.  We're not trying to add 100% unit test coverage for the AccountFilter class, just to test the changes we're making.

Not knowing if I can unit test this class, the easiest way to see if it's testable is to try using it in a test.  Here's the behavior I want, in a unit test:

[TestMethod]
public void Should_not_add_filter_when_basket_is_a_quote()
{
    ShoppingCart cart = new ShoppingCart();
    cart.IsQuote = true;
    cart.AccountNumber = "123ABCD";

    AccountFilter filter = new AccountFilter(new string[] { "CRD", "INV" });
    filter.AddPaymentOptions(cart);

    Assert.AreEqual(0, cart.PaymentFilters.Count);
}

I try running this test, and it fails spectacularly.  The error I get is along the lines of "HttpContext.Current is null", so something is dependent on the ASP.NET runtime being up.

Looking at the AddPaymentOptions method of the AccountFilter class, I notice the call to the static method FindPaymentByType on the ProfileManager class.  That method is extremely hideous, with hard dependencies on HttpContext.Current, a web service, and a database.  Instead of focusing on breaking those dependencies out, I can apply Inline Static Class and break out AddPaymentOptions' dependency on ProfileManager.  The end goal is to break the dependencies of the class I'm trying to test, not all the sub-sub-sub dependencies that may be around.

Step 1:

ProfileManager is a huge class, with about 100 different methods.  The only one I'm interested in is the FindPaymentByType method, so I'll create an IProfileManager interface that includes only that method, matching signature and name.

public interface IProfileManager
{
    IPayment FindPaymentByType(string[] paymentTypes);
}

Step 2:

Now that I have my IProfileManager, I'll make the static class implement the new interface.  Note that the static class itself isn't marked "static", only its methods.  Additionally, I'll need to explicitly implement that method so it doesn't conflict with the existing static method.

public class ProfileManager : IProfileManager
{
    public static IPayment FindPaymentByType(string[] paymentTypes)
    {
        // Hit web service for widget
        // Query database based on widget
        // Return database object
    }

    IPayment IProfileManager.FindPaymentByType(string[] paymentTypes)
    {
        return null;
    }
}

I compile, and everything looks good.  Notice I didn't add any access modifiers to the new IProfileManager method, and the inclusion of the interface name prefixed on the method name.  That's how I can explicitly implement the interface, and not get any compile errors even though these two methods have the exact same signature.

Step 3, 4:

Now I can move the existing implementation to the new interface method, and use Hide Delegate to change the static method to call the new interface method.  I don't want to introduce duplication and simply copy over the implementation, so Hide Delegate allows me to retain backwards compatibility and save a lot of work of changing all clients to use the new method.

public class ProfileManager : IProfileManager
{
    public static IPayment FindPaymentByType(string[] paymentTypes)
    {
        IProfileManager profileManager = new ProfileManager();
        return profileManager.FindPaymentByType(paymentTypes);
    }

    IPayment IProfileManager.FindPaymentByType(string[] paymentTypes)
    {
        // Hit web service for widget
        // Query database based on widget
        // Return database object
    }
}

Now my static method delegates to the instance methods, and no other clients are affected by this change.  Again, it's not my goal to fix every client dependency on this static method, only the one I'm changing.

I compile and test, but my initial unit test is failing as it's still calling the static method.

Step 6:

Now that I have an interface to depend upon instead of a static method, I'll change the client code to use the interface instead of the static method.  It looks much like the code inside the Hide Delegate of the static method:

public void AddPaymentOptions(ShoppingCart cart)
{
    IProfileManager profileManager = new ProfileManager();
    IPayment payment = profileManager.FindPaymentByType(_paymentTypes);

    if ((payment != null) &&
        (! string.IsNullOrEmpty(cart.AccountNumber)))
    {
        cart.PaymentFilters.Add(payment);
    }
}

I create a variable of type IProfileManager, instantiate it to a ProfileManager instance, and use the IProfileManager.FindPaymentByType method instead of the static method.  I compile and test, but my unit test still fails as I still haven't fully extracted the dependency on the ProfileManager, but that will be taken care of shortly.

Step 8:

I have two options, I can either pass in the IProfileManager as in the method call or I can pass it in through the constructor.  I prefer to pass dependencies through constructors over method parameters, because I like a clear separation between queries, commands, and dependencies.  Additionally, if I'm using an IoC container, I can wire up these dependencies a little more easily.  I'll use Preserve Signatures [Feathers 312] and Chain Constructors to keep the original constructor, as there are still quite a few clients of my AccountFilter class that I don't want to change:

public class AccountFilter
{
    private readonly string[] _paymentTypes;
    private readonly IProfileManager _profileManager;

    public AccountFilter(string[] paymentTypes)
        : this(paymentTypes, new ProfileManager()) { }

    public AccountFilter(string[] paymentTypes, IProfileManager profileManager)
    {
        _paymentTypes = paymentTypes;
        _profileManager = profileManager;
    }

    public void AddPaymentOptions(ShoppingCart cart)
    {
        IPayment payment = _profileManager.FindPaymentByType(_paymentTypes);

        if ((payment != null) &&
            (!string.IsNullOrEmpty(cart.AccountNumber)))
        {
            cart.PaymentFilters.Add(payment);
        }
    }
}

So I did a few things here:

  • Add a new constructor that took an IProfileManager, and created the backing field for it
  • Make the other constructor call the new one, passing in a new ProfileManager, which is what existing code would do
  • Make the AddPaymentOptions method use the field variable instead of a local variable

What this code allows me to do is pass in a different IProfileManager instance in my test methods to verify my behavior.  I don't really care what the ProfileManager does, all I care about is what it tells me.  Somewhere down the line, I have an integration test that puts the two together, but until then, my unit test will suffice.  Here's my final unit test, which fails for the reason I want it to fail, because the assertion fails:

[TestMethod]
public void Should_not_add_filter_when_basket_is_a_quote()
{
    ShoppingCart cart = new ShoppingCart();
    cart.IsQuote = true;
    cart.AccountNumber = "123ABCD";

    string[] paymentTypes = new string[] { "CRD", "INV" };

    MockRepository repo = new MockRepository();

    IProfileManager profileManager = repo.CreateMock<IProfileManager>();

    using (repo.Record())
    {
        Expect.Call(profileManager.FindPaymentByType(paymentTypes))
            .Return(null);
    }

    using (repo.Playback())
    {
        AccountFilter filter = new AccountFilter(paymentTypes, profileManager);
        filter.AddPaymentOptions(cart);
    }

    Assert.AreEqual(0, cart.PaymentFilters.Count);
}

I use RhinoMocks to pass in a mock IProfileManager, and test-driven development to add the functionality desired.  I broke the dependency of the class under test away from the ProfileManager static method, and was able to preserve existing functionality.  By preserving existing interfaces and functionality, I can eliminate much of the risk involved in changing legacy code.  I got my changes in, was able to test them, and kept out of the rabbit-hole that a larger refactoring would have thrown me into.

Wednesday, August 29, 2007

Template Delegate Pattern

I've had to use this pattern a few times, most recently in Behave#.  It's similar to the Template Method pattern, but doesn't resort to using subclassing for using a template method.  Instead, a delegate is passed to the Template Method to substitute different logic for portions of the algorithm.

The pattern

Two methods in unrelated classes perform similar general algorithms, yet some parts of the algorithm are different.

Generalize the algorithm by extracting their steps into a new class, then extract methods for the specialized parts into delegates to be passed in to the new class.

Motivation

Helper methods tend to clutter a class with responsibilities orthogonal to its true purpose.  Additionally, several methods in one class might need to perform the same algorithm in slightly different ways.  While Template Method is concerned with removing behavioral duplication, algorithmic duplication can be just as rampant. 

Removing algorithmic duplication through Template Method can make the code more obtuse, as often the abstraction of the template class doesn't add any meaning to the system.  Additionally, sometimes duplicate algorithms are in completely separate classes, and it would be impossible or unwise to try to extract a common subclass from the two classes.  We can remove algorithmic duplication by consolidating the algorithm into its own method or class, and pass in parts of the algorithm that might vary.

Mechanics

  • Use Extract Method to separate the purely algorithmic section of each method from any surrounding behavioral code.
  • Compile and test.
  • Decompose the methods in each algorithm so that all of the steps in the algorithm are identical or completely different.
  • For each step in the algorithm that is completely different, use Extract Method to pull out the varying logic.  Name these extracted methods the same.
  • Compile and test.
  • Optionally, use Introduce Parameter Object for each extracted algorithm method that does not match the same number of parameters for the other different algorithm steps.  Compile and test.
  • If there is not an existing delegate type that matches the extracted variant methods of the algorithm, create a delegate type that matches both extracted methods.
  • Use Add Parameter and add a new parameter of the delegate type created earlier, and modify the algorithm to use the delegate method to execute the varying logic.  Repeat for both algorithm methods.  Each algorithm method should look exactly the same at this point, except for parameter and return types.
  • Compile and test.
  • Use Extract Class and Move Method to move the two algorithm methods to a new, generalized (and optionally generic) class.  Modify the calling class to use the new class and methods.
  • Compile and test.

Example

Suppose I find the two methods in different classes in a large codebase that do recursive searches.  One finds a Control based on an ID, and the other searches for XmlNodes based on an attribute value:

private Control FindControl(ControlCollection controls)
{
    foreach (Control control in controls)
    {
        if (control.ID == txtControlID.Text)
            return control;

        return FindControl(control.Controls);
    }
}

private XmlNode FindElement(XmlNodeList nodes)
{
    foreach (XmlNode node in nodes)
    {
        if (node.Attributes["ID"].Value == "4564")
            return node;

        return FindElement(node.ChildNodes);
    }
}

Both of these methods perform the exact same logic, a recursive search, but the details are slightly different.

In this example, the first step is already complete and each method contains only the algorithm I'm interested in.  From looking at these methods, it looks like there are 3 distinct parts: the loop, the comparison, and the actual matching logic.  The two differing parts I see in the algorithm are:

  • Match
  • Get the children based on the current item in the loop

I'll apply Extract Method to pull out the varying logic and name these methods the same.  Here are the extracted methods:

private bool IsMatch(Control control)
{
    return control.ID == txtControlID.Text;
}

private bool IsMatch(XmlNode node)
{
    return node.Attributes["ID"].Value == "4564";
}

private ControlCollection GetChildren(Control control)
{
    return control.Controls;
}

private XmlNodeList GetChildren(XmlNode node)
{
    return node.ChildNodes;
}

Note that the names of each method is the same, as well as the number of parameters.  Now the original algorithm methods call these extracted varying methods:

private Control FindControl(ControlCollection controls)
{
    foreach (Control control in controls)
    {
        if (IsMatch(control))
            return control;

        return FindControl(GetChildren(control));
    }
}

private XmlNode FindElement(XmlNodeList nodes)
{
    foreach (XmlNode node in nodes)
    {
        if (IsMatch(node))
            return node;

        return FindElement(GetChildren(node));
    }
}

These algorithm methods are starting to look very similar.  Next, I need to find a delegate type to represent the varying methods, namely "IsMatch" and "GetChildren".  Since I'm working with Visual Studio 2008, some good candidates already exist with the Func delegate types.  I like these delegate types as they are generic and may lend to some better algorithm definitions in the future, so I'll stick with Func.  Here's the FindControl method after I use Add Parameter to pass in the varying algorithm logic:

private Control FindControl(IEnumerable<Control> controls, 
    Func<Control, bool> predicate,
    Func<Control, IEnumerable<Control>> childrenSelector)
{
    foreach (Control control in controls)
    {
        if (predicate(control))
            return control;

        return FindControl(childrenSelector(control), predicate, childrenSelector);
    }
}

I changed the type of the "controls" parameter to IEnumerable<Control> from ControlCollection, to reduce the number of types seen in the algorithm method.  I change the client code of this algorithm to pass in the new parameters, compile and test:

private void SetLabelText()
{
    string text = txtLabelText.Text;
    string controlID = txtControlID.Text;

    if (string.IsNullOrEmpty(text) || string.IsNullOrEmpty(controlID))
        return;

    Control control = FindControl(page.Controls, IsMatch, GetChildren);
}

Note that the "IsMatch" and "GetChildren" are method names in this class, so I'm passing the matching and children algorithms to the FindControl method for execution when needed.  Finally, I use Extract Class and Move Method to move the two virtually identical algorithm methods to a single method on a new class.  Here's the final result, with some minor changes to use extension methods:

public static T RecursiveSearch<T>(this IEnumerable<T> items,
    Func<T, bool> predicate,
    Func<T, IEnumerable<T>> childrenSelector)
{
    foreach (T item in items)
    {
        if (predicate(item))
            return item;

        return RecursiveSearch(childrenSelector(item), predicate, childrenSelector);
    }

    return default(T);
}
 

I've made the method generic, as the only final variant between the extracted algorithm methods was the type of the item I was finding.  By making the method generic, the return type is strongly typed to the item I'm searching for.  The final client code doesn't look too much different from earlier:

private void SetLabelText()
{
    string text = txtLabelText.Text;
    string controlID = txtControlID.Text;

    if (string.IsNullOrEmpty(text) || string.IsNullOrEmpty(controlID))
        return;

    Control control = page.Controls.Cast<Control>().RecursiveSearch(IsMatch, GetChildren);
}

The client code for the "FindElement" looks exactly the same, and now there is no duplication of the recursive search logic.  I've extracted the varying logic into methods which can be passed in as delegates to the new, generic extracted algorithm.  Since I'm using C# 3.0, I can go as far as using lambda expressions instead of the extracted "IsMatch" and "GetChildren" methods.

Conclusion

The Template Delegate pattern is used quite extensively with the new Enumerable extension methods (such as the Where method).  With delegate creation in C# 3.0 becoming much simpler with lambda expressions, it's becoming easier to compose generalized algorithms where varying portions are passed in as delegate parameters.  By using the Template Delegate pattern, I can reduce the number of junk algorithmic methods into a single generic class that serves the needs of current and future client code.