Killing the Helper class, part two

Earlier this week, I blogged on the evils of helper classes.  I got a few very thoughful responses, and I wanted to try to address one of them.  It is far easier to do that with a new entry that trying to respond in the messages.

If you didn't read the original post, I evaluated the concept of the helper class from the standpoint of one set of good principles for Object Oriented development, as described by Robert Martin, a well respected author and speaker.  While I don't claim that his description of OO principles is "the only valid description as annointed by Prophet Bob", I find it extremely useful and one of the more lucid descriptions of fundamental OO principles available on the web.  That's my caveat.

The response I wanted to address is from William Sullivan, and reads as follows:

I can think of one case where helper classes are useful... Code re-use in a company. For instance, a company has a policy on how its programs will access and write to the registry. You wouldn't want some products in the company saving its data in HKLM/Software/CompanyName/ProductName and some under .../Software/ProductName and some .../"Company Name"/"Product Name". So you create a "helper class" that has static functions for accessing data in the registry. It could be designed to be instantiatable and extendable, but what would be the advantage? Another class could implement the companies' policy on encryption, another for database access;[clip]

If you recall, my definition of a helper class is one in which all of the methods are static.  It is essentially a set of procedures that are "outside" the object structure of the application or the framework.  My objections were that classes of this nature violate two of the principles: the Open Closed Principle, and the Dependency Injection Principle.

So, let's look at what a company can do to create a set of routines like William describes. 

Let's say that a company (Fabrikam) produces a dozen software systems.  One of them, for our example, is called "Enlighten".  So the standard location for accessing data in the registry would be under HKLM/Software/Fabrikam/Enlighten.  Let's look at two approaches: one using a helper class and one using an instantiated object:

class HSettings
{
   static String GetKey(String ProductName, String Subkey)
   {   // -- interesting code  
   }
}

class FSettings
{
     private string _ProductName;
     public FSettings (String ProductName)
     {   _ProductName = ProductName;
     }
     public String GetKey(String Subkey)
     {  // nearly identical code
     }
}

Calling the FSettings object may look to be a little more effort:

public String MyMethod()
{   FSettings fs = new FSettings("Enlighten");
    string Settingvalue = fs.GetKey("Mysetting");
    //Interesting code using Settingvalue
}

as compared to:

public String MyMethod()
{   string Settingvalue = HSettings.GetKey("Enlighten","Mysetting");
    //Interesting code using Settingvalue
}

The problem comes in unit testing.  How do you test the method "MyMethod" in such a way that you can find defects in the 'Interesting Code' without also relying on any frailties of the code buried in our settings object.  Also, how to test this code without there being any setting at all in the registry?  Can we test on the build machine?  This is a common problem with unit testing.  How to test the UNIT of functionality without also testing any underlying dependencies. 

When a function depends on another function, you cannot easily find out where a defect is causing you a problem.  A defect in the dependency can cause a defect in the relying code.  Even the most defensive programming won't do much good if the dependent code returns garbage data.

If you use the Dependency Injection Principle, you can get code that is a lot less frail, and it easily testable.  Let's refactor our "FSettings" object to inherit from an interface.  (This is not something we can do for the HSettings class, because it is a helper class).

 

Interface ISettings
{
     public String GetKey(String Subkey);

}
class FSettings : ISettings // and so on

Now, we refactor our calling code to use Dependency Injection:

public class MyStuff {
private ISettings _fs; public MyStuff() {
    _fs = new FSettings("Enlighten");
}
public SetSettingsObject(ISettings ifs)
{
    _fs = ifs;
}
public String MyMethod()
{    string Settingvalue = _fs.GetKey("Mysetting");
    //Interesting code using Settingvalue
}
}

Take note: the code in MyMethod now looks almost identical to the code that we proposed for using the static methods. The difference is important, though. First off, we seperate the creation of the dependency from it's use by moving the creation into the constructor. Secondly, we provide a mechanism to override the dependent object.

In practical terms, the code that calls MyMethod won't care. It still has to create a 'MyStuff' object and call the MyMethod method. No parameters changed. The interface is entirely consistent. However, if we want to unit test the MyMethod object, we now have a powerful tool: the mock object.

class MockSettings : ISettings
{
     public MockSettings (String ProductName)
     {   if (ProductName != "Enlighten")
        throw new ApplicationException("invalid product name");
     }
     public String GetKey(String Subkey)
     {  return "ValidConnectionString";
     }
}

So, our normal code remains the same, but when it comes time to TEST our MyMethod method, we write a test fixture (a method in a special class that does nothing but test the method). In the test fixture, we use the mock object:

class MyTestFixture
{
     public void Test1 ()
     {   MyStuff ms = new MyStuff();
         MockSettings mock = new MockSettings();
         ms.SetSettingsObject(mock);
            // now the code will use the mock, not the real one.
         ms.MyMethod();
        // call the method... any exceptions?

      }
}

What's special about a test fixture? If you are using NUnit or Visual Studio's unit testing framework, then any exceptions are caught for you.

This powerful technique is only possible because I did not use a static helper class when I wanted to look up the settings in my registry.

Of course, not everyone will write code using unit testing. That doesn't change the fact that it is good practice to seperate the construction of an object from it's use. (See Scott Bain's article on Use vs. Creation in OO Design).  It also doesn't change the fact that this useful construction, simple to do if you started with a real object, requires far more code change if you had started with a helper class.  In fact, if you had started with a helper class, you may be tempted to avoid unit testing altogether. 

I don't know about you, but I've come across far too much code that needed to be unit tested, but where adding the unit tests would involve a restructuring of the code.  If you do yourself, and the next programmer behind you, a huge favor and simply use a real object from the start, you will earn "programmer's karma" and may inherit some of that well structured code as well.   If everyone would simply follow "best practices" (even when you can't see the reason why it's useful in a particular case), then we would be protected from our own folly most of the time.

So, coming back to William's original question: "it could be designed to be instantiable and extendable, but what's the advantage?"

The advantage, is that when it comes time to prove that the calling code works, you have not prevented the use of good testing practices by forcing the developer to use a static helper class, whether he wanted to or not.