Helpers vs Extenders

One of the most important features we need to achieve in our life as developers is to write code which at some point can be reused. Reuse is tricky word because sometimes we find ourselves saying “it just needs a tiny modification” when it needs some major rewriting. Making reusable code is not just writing a snippet of code and then copy it and write it down again, it’s having libraries of code that don’t need any sort of modification (in the worst case scenario, some small ones).


This takes me to the point of this post, which is considering method extensions when developing applications. Let’s see the following problem, suppose we need for a certain task to retrieve the names of the properties available in an object, but we need to make this as generically as possible, because we don’t know when we could need the same feature again.


The initial approach is to do a small static class which does the job, most people tend to call these classes helpers. Helpers are there to “help” our code doing stuff that might be needed by several parts of the same application. To our problem, the helper code would look like this:


public static class ReflectionHelper
{
    public static List GetMethods( object who )
    {
        //Implementation of the method
    }
}

This approach does work most times, but is not nice in the refactoring sense of development. We need to keep these kinds of helper objects to the smallest amount in any design we make, because by following this pattern, we can end up in one of two possible scenarios.


The first possible ending is that we might end up with a few helper classes doing just a few functionalities, sometimes providing a really horrible refactoring nightmare. The second possible scenario is that we might end up with one monster helper with a lot of helper methods, which will make the previous nightmare look like a pleasant dream.


There are two more plausible solutions to this problem. The first one applies to the case where retrieving the list of methods is part of the work of our objects; to this case we could apply the scenario of an ORM framework when it’s mapping the properties to an object and retrieves the properties using reflection. Anyways, in this case we could add a base class called ReflectableObject, which provides all the required functionalities.


If we choose to follow the ORM sample, we would have a class diagram having a Model class and to complicate things a bit, we could also have a repository class. Both would need to perform some sort of reflection on the objects they manage, so they would require it. The class diagram would be like this:



This way works pretty well for the cases where we want to include this behavior into the object, but this does pose a few problems:


  • We would need to add an extra layer of classes to our design, thus complicating the design
  • When we have only one class needing to perform the actual operation we need to create, adding another layer of complexity would feel like killing a fly with a rail gun.
  • If by any chance of fate we are working with sealed classes, inheritance is automatically discarded.

Finally, there is one last option: Using extension methods. Extension methods are there to provide a flexible and reusable way to extend objects that are there already, and we do not want to either modify or inherit.


We can think of extensions as a light inheritance, we say: “OK, we have this class and we want to add a few methods to it, but we don’t want to create a new class and inherit from it, so what do we do?”

We extend the class.

The code to extend a class is quite similar to the helper, but instead we include a reference to the class we are planning to extend in the method, like this:


public static class ReflectionHelper 
{ 
     public static List GetMethods( this object who ) 
     {
          //Implementation of the method 
     } 
} 

Is quite simple, suppose that our class is in the ReflectionHelpers namespace, we would be able to do this then:


using ReflectionHelpers; 
using System; 

namespace MyNamespace 
{ 
    public class MyClass 
    { 
        public void Foo() 
        {
            object o = SomeWeirdOperation(); 
            var methods = o.GetMethods(); 
        } 
    } 
}

All objects can call now the GetMethods method! By doing this we are successfully removing the extra layer from the design, we are getting the job done and it doesn’t requires new classes to be added, if we change the ReflectionHelper class name to Reflexive it wouldn’t matter, because all that matters is that the GetMethods method is extending the object class as specified in the object signature.

Extension methods are the base of LINQ, and perhaps one of the most powerful tools implemented in the .NET framework.

No comments:

Post a Comment

Commenting is allowed!