May 16

The strategy pattern is a way to inject algorithms into a chunk of code, or as I like to think of it, basically a way to refactor out multiple lines of code and pass them into a method. Let’s look at an example.

Say you have a method with some hard coded strings:

public string WrapWithSingleQuote(string text)
{
	return "'" + text + "'";
}

Now in your next iteration you’re asked to wrap any needed text in double quotes and/or parenthesis. Being the awesome developer that you are, you generalize the method like so:

public string WrapWithString(string text, string wrapper)
{
	return wrapper + text + wrapper;
}

See that? The wrapper parameter that allowed you to pass whatever you want to wrap the text in? That’s a simplistic and primitive example of the strategy pattern, but an example nonetheless. Now the method allows you to wrap the given text in whatever characters your heart desires.

Now for a bit more robust and real world example of the pattern. Let’s consider the .NET WinForm’s TextBox control. This control has auto-complete functionality built into it to, able to suggest completed entries based off the currently entered text from a variety of sources: file system, URL’s, a custom source, and more.

A few requirements come in stating that the users want auto-completion for the company text box in their mythical application, so you whip up the following user control:

public partial class CompanyFindTextBox : TextBox
{
	public CompanyFindTextBox()
	{
		InitializeComponent();
		this.AutoCompleteMode = AutoCompleteMode.Suggest;
		this.AutoCompleteSource = AutoCompleteSource.CustomSource;
	}
 
	public CompanyFindTextBox(IContainer container)
		: this()
	{
		container.Add(this);
	}
 
	protected override void OnKeyUp(KeyEventArgs e)
	{
		HandleAutoComplete(this.Text.Trim());
		base.OnKeyUp(e);
	}
 
	private void HandleAutoComplete(string searchText)
	{
		if(searchText != string.Empty)
		{
			using(DatabaseDataContext db = new DatabaseDataContext())
			{
				var matchingCompanies =
					from c in db.Companies
					where c.Name.ToUpper().StartsWith(searchText)
					orderby c.Name
					select c.Name;
 
				this.AutoCompleteCustomSource.AddRange(matchingCompanies.ToArray());
			}
		}
	}
}

Now, of course, the users want the same functionality on their job, candidate, contractor, and who knows what other text boxes. Looks like a refactoring is in order. Ah, but this time there isn’t a simple string to extract as a parameter to fix the problem! You need to generalize your LINQ statement, but each text box type is searching on different databases, fields, etc.

This where the power of the strategy pattern comes in. With it, you can tell the control/method how to go about executing a certain algorithm. Specifically, in C# we usually use delegates (which are nothing more than methods passed into other methods as parameters – or function points from lower level languages). Since C# 3.0 introduced lambdas (simply more concise ways to declare delegates), let’s go ahead and use those. Here’s a more generalized user control which uses the strategy pattern to pull out the specific database accessing code:

public partial class EntityFindTextBox : TextBox
{
	public Func AutoCompleteStrategy { get; set; }
 
	public EntityFindTextBox()
	{
		InitializeComponent();
		this.AutoCompleteMode = AutoCompleteMode.Suggest;
		this.AutoCompleteSource = AutoCompleteSource.CustomSource;
	}
 
	public EntityFindTextBox(IContainer container)
		: this()
	{
		container.Add(this);
	}
 
	protected override void OnKeyUp(KeyEventArgs e)
	{
		HandleAutoComplete(this.Text.Trim());
		base.OnKeyUp(e);
	}
 
	private void HandleAutoComplete(string searchText)
	{
		if(AutoCompleteStrategy != null && searchText != string.Empty)
		{
			this.AutoCompleteCustomSource.AddRange(AutoCompleteStrategy(searchText));
		}
	}
}

Notice how this implementation has a function property named AutoCompleteStrategy. This says we’re looking for a method that takes in a string and returns an array of strings. Now in the HandleAutoComplete method, we make sure this isn’t null and call it with the text box’s contents. This abstracts out the actual database searching algorithm so the new user control can be used with any type of entity the system needs, be it companies, jobs, contractors, etc. That’s the strategy pattern in all its glory.

After dropping the new control on a form, you might set it up for a company like so:

txtCompanies.AutoCompleteStrategy = (searchTerm =>
	{
		using(DatabaseDataContext db = new DatabaseDataContext())
		{
			var matchingCompanies =
				from c in db.Companies
				where c.Name.ToUpper().StartsWith(searchText)
				orderby c.Name
				select c.Name;
			return matchingCompanies.ToArray();
		}
	});

Now we’re setting the AutoCompleteStrategy property to a new lambda expression (think quick method declaration) that’s accepting a string parameter named searchTerm and using it in the same LINQ query from before, ultimately returning an array of company names which contain whatever was passed in. We could do this for a job text box just as easily, simply swapping out the LINQ statement for a new one (or even XML file searching, a web service call, whatever).

Simple enough, right?

May 9

The background

A Data Transfer Object (DTO) is a plain old CLR object (POCO) mainly used to pass data between tiers and remote calls. They’re basically classes with getters, setters, and perhaps a constructor or two, but no methods. They’re dumb objects that simply hold data.

So why would you use these? A few reasons:

  1. They flatten your data. DTO’s can contain information from a multitude of sources (database, XML, web service, etc) all neatly packaged together, including any large hierarchies of data from your relational (SQL) store.
  2. They more easily allow parameters to be passed into and out of methods, especially expensive ones like web services. You’re not forced to break a web service’s signature if you need to add/remove parameters if you pass in a DTO. The DTO can change and clients aren’t forced to immediately update. They also help keep method signatures nice and tidy.
  3. They help decouple your layers by remaining technology and location agnostic. If your relational data moves around, you simply have to modify your data layer (or your business layer if you’re passing DTO’s back for presentation reasons) to get the needed information. The consuming layer won’t care that the data is coming from somewhere else, they’re just looking at the DTO’s copy.

The setup

Let’s look at a simple scenario. We’re loading a business object and calling out to our data layer for the information, which we’ll get from SQL using LINQ to SQL. The following DTO will be passed back:

public class PersonDTO
{
	public string FirstName { get; set; }
	public string LastName { get; set; }
	public int Age { get; set; }
	public decimal HourlyWage { get; set; }
}

The code

Let’s look at the GetPerson method from the data layer, which uses LINQ to SQL to retrieve the needed information from SQL:

public PersonDTO GetPerson(int personID)
{
	using(DatabaseDataContext db = new DatabaseDataContext())
	{
		return (from p in db.Peoples
			    join pw in db.PeopleWages on p.PersonID equals pw.PersonID
			    where p.PersonID == personID
			    select new PersonDTO
			    {
					FirstName = p.FirstName,
					LastName = p.LastName,
					Age = p.Age,
					HourlyWage = pw.HourlyWage
			    }
			   ).SingleOrDefault();
	}
}

The key bit is the select new PersonDTO and its four accompanying lines. It might look a bit odd, but it’s the new object initializer syntax added to C# 3.0. The compiler is basically creating a constructor in the background, taking in the specified parameters, and setting their respective property values.

This keeps your simple select methods such as this visually clean. No need to return a LINQ object and set each property in a separate call. OK, not a huge positive, but hey, it’s the small things that count. I personally love clean, slick, code.

Also note the SingleOrDefault() call at the end, which will return a single object from the LINQ statement (which in this case is of type PersonDTO) or a default value for that object if one isn’t found (and since we’re selecting a reference type, it’d return null). SingleOrDefault() will throw an exception if more than one record is returned from SQL, but since we’re looking for a primary key here, it shouldn’t be a problem.

As a side note, one of the neat features of Visual Studio 2008 is the IntelliSense’s ability to filter the already assigned properties within the object initializer portion of the LINQ statement. For instance, notice how it’s hiding the FirstName property in the pop-up since I assigned it in the line above:

IntelliSense filtering the available properites

To wrap up, here’s the CreatePerson method, on the Person object in the business layer, that would consume the above GetPerson method:

public Person CreatePerson(int personID)
{
	using(PersonDTO personDTO = DataLayer.GetPerson(personID))
	{
		return new Person
		{
			FirstName = personDTO.FirstName,
			LastName = personDTO.LastName,
			Age = personDTO.Age,
			HourlyWage = personDTO.HourlyWage
		};
	}
}

Notice how it too is making use of the new object initializer feature.