Are extensive extension method an anti-pattern

I was explaining my dilemma to a Java friend and the e-mail ended up being fairly interesting, so I thought I would share it.

I’m sure Java has extension methods, but I’ll give it a once over just in case.  You can extend existing classes without sub-classing by extension methods.

public static IEnumerable<SelectListItem>
                            AsSelectListItems( this IEnumerable<Person> listOfPeople){
   IList<SelectListItem> selectListItems = new List
();
   foreach(var person in listOfPeople){
      selecListItems.Add(new SelectListItem(person.ID,
					    string.Format("{0} {1} {2}",
                                                          person.First,
                                                          person.Middle,
                                                          person.Last));
   }
   return selectListItems;
}

Right. So the this operator tells the compiler to basically create this function:

public static IEnumerable<SelectListItem>
                           AsSelectListItems(IEnumerable<Person> listOfPeople);

And invoke it every time you see this:

IEnunerable<Person> p = myService.GetAllPeople();
IEnumerable<SelectListItem> s = p.AsSelectListItems();

You probably knew all this, but it explains how we are using them. We end up calling a lot of extension methods off other extension methods.

myViewData.PersonSelectListItems = myService.GetAllPeople()
                                                   .AsSelectListItems()
                                                   .OrderedByText()
                                                   .StartingWithAnEmptyItem();

In this example we have three extension method calls and I think it really makes the code much more readable, but it makes testing this code a little more difficult. Obviously, the myService is a mocked dependency which will return a fake list of people, but the other extension method calls cannot be mocked, and the scope of the test bleeds a bit.

I like the syntax it gives, but now I’m going to test potentially four classes when I should be testing only one.

This gets pretty pandemic in our code. Especially trying to make Selenium’s API and the assertion API of Nunit and xUnit more fluent.

Leave a Reply