fooberry

Sweetness without context.

Are extensive extension method an anti-pattern

November 30th 2009

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&lt;Person&gt; listOfPeople){

IList<SelectListItem> selectListItems = new List(); foreach(var person in listOfPeople){

  selecListItems.Add(new SelectListItem(person.ID, 
                    string.Format(&quot;{0} {1} {2}&quot;, 
                                                      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&lt;Person&gt; listOfPeople);</pre>

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();</pre>

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 Seleniums API and the assertion API of Nunit and xUnit more fluent.

blog comments powered by Disqus