Using Extension Methods to make code more readable.

Let’s look at an example:

  diagramThis is somewhat simplified diagram of classes that are part of object model I created for a certain XML format (it doesn’t reflect physical structure of XML file, rather it’s a conceptual, higher level model).

Document can contain few types of elements. To achieve this, it has a method Add, that takes a ValueElement (which is an abstract class).

The problem here, is that it is not obvious what is a ValueElement. You have to know what you can put into Add method, which means, you have to know what ValueElement’s children are. Their names however reflect their other properties, not the fact that they are value elements, which makes it even harder to guess.  You’d have to poke around in the source code to find out.

diagram_document  Why not create Add overload for each value element then? – one might ask, This way IntelliSence would hint us on what are available value elements, would it not?

diagram_code1 Well, it would but it would fix one thing and break few others.

It ties, Document to ValueElement’s hierarchy. This way, every time a new ValueElement’ descendant is added, we would have to change document as well, to add yet another overload to Add.

Why not leave general overload as a catch-all, and add overloads for those descendants we know about?

Well, this is not a good option either. At this point Document doesn’t really care about specific ValueElement. All it needs to know is that it receives a ValueElement. Telling it more, would be telling it too much. Also adding handful of new overloads would bloat the class, and introduce big-class smell.

diagram_extension This is actually one place, where I think Extension Methods would prove useful. I would introduce an extension class, that would keep all specific overloads, calling the only Document’s Add under the cover. This way, Document does not gain any more knowledge about value elements, than it needs to, and users get IntelliSence hints about what they can actually Add to Document.diagram_code2

It could be made even a little bit more verbose, by creating specific methods for each value element, instead of Add’ overloads

public static void AddText(this Document document, Text text)

{ document.Add(text); }

 

public static void AddTranslationUnit(this Document document, TranslationUnit unit)

{ document.Add(unit); }

 

public static void AddUnknownTag(this Document document, UnknownTag tag)

{ document.Add(tag); }

If I was to make a design pattern out of this, I would call it Godfather, partially because I think it’s a cool namesmile_teeth, and partially because DocumentAddExtension (our Godfather class in this example) knowledge about ValueElement’s descendants (its godchildren) and it provides this knowledge to the user, but hides it from the class it’s tied to (Document). Also important thing is, that it’s not part of ValueElement’s inheritance hierarchy (that’s why it’s called Godfather, instead of, ‘Uncle Fred’ or something like thissmile_wink).