First off, a definition: A helper class is a class filled with static methods. It is usually used to isolate a “useful” algorithm. I’ve seen them in nearly every bit of code I’ve reviewed. For the record, I consider the use of helper classes to be an antipattern. In other words, an extraordinarily bad idea that should be avoided most of the time.
What, you say? Avoid Helper Classes!?! But they are so useful!
I say: they are nearly always an example of laziness. (At this point, someone will jump in and say “but in Really Odd Situation ABC, There Is No Other Way” and I will agree. However, I’m talking about normal IT software development in an OO programming language like C#, Java or VB. Net. If you have drawn a helper class in your UML diagram, you have probably erred).
Why laziness? If I have to pick a deadly sin, why not gluttony? 🙂
Because most of us in the OO world came out of the procedural programming world, and the notion of functional decomposition is so easy that we drop to it when we come across an algorithm that doesn’t seem to “fit” into our neat little object tree, and rather than understand the needs, analyze where we can get the best use of the technology, and place the method accordingly, we just toss it into a helper class. And that, my friends, is laziness.
So what is wrong with helper classes? I answer by falling back on the very basic principles of Object Oriented Programming. These have been recited many times, in many places, but one of the best places I’ve seen is Robert Martin’s article on the principles of OO. Specifically, focus on the first five principles of class design.
So let’s look at a helper class on the basis of these principles. First, to knock off the easy ones:
Single Responsibility Principle – A class should have one and only one reason to change – You can design helper classes where all
of the methods related to a single set of responsibilities. That is entirely possible. Therefore, I would note that this principle does not conflict with the notion of helper classes at all. That said, I’ve often seen helper classes that violate this principle. They become “catch all” classes that contain any method that the developer can’t find another place for. (e. g. a class containing a helper method for URL encoding, a method for looking up a password, and a method for writing an update to the config file… This class would violate the Single Responsibility Principle).
Liskov Substitution Principle – Derived classes must be substitutable for their base classes – This is kind of a no-op in that a helper class cannot have a derived class. (Note my definition of a helper class is that all members are static). OK. Does that mean that helper classes violate LSP? I’d say not. A helper class looses the advantages of OO completely, an in that sense, LSP doesn’t matter… but it doesn’t violate it.
Interface Segregation Principle – Class interfaces should be fine-grained and client specific – another no-op. Since helper classes do not derive from an interface, it is difficult to apply this principle with any degree of seperation from the Single Responsibility Principle.
Now for the fun ones:
The Open Closed Principle – classes should be open for extension and closed for modification – You cannot extend a helper class. Since all methods are static, you cannot derive anything that extends from it.